我需要为stl算法设计谓词,例如find_if,count_if。

namespace lib
{
    struct Finder
    {
        Finder( const std::string& name ):
            name_( name )
        {
        }

        template< typename TElement >
        bool operator( const TElement& element )
        {
            return element.isPresent( name_ );
        }

        /* template< typename TElement >
        bool operator( const TElement& element )
        {
            const Data& data = element.getData();
            return data.isPresent( name_ );
        }*/ 
    };
}

但是我需要它根据TElement中某些特定方法的存在而拥有不同的operator()。就好像它有“getData”一样我想检查一下这些数据,如果没有,我会做其他一些操作。

我知道SFINAE。但我在项目上没有boost ::。 因此,要么有一些简单的模板实现“has_method”,或者你知道其他一些设计方案。

我无法指出特定的类型并且只是重载,因为我想把这个Predicate放到项目库中,它不知道带有“getData”的那些特定类。方法

只要没有名称空间,具有类特征的解决方案就很好。在“lib”中的谓词查找器带有“getData”的名称空间和类是在“程序”中命名空间。

感谢。

有帮助吗?

解决方案

为什么要使用模板mathods?如果有很多类类型,只需使用您希望基于它的特定类或公共基类。

e.g。

struct Finder
{
    Finder( const std::string& name ):
        name_( name )
    {
    }

    bool operator( const IsPresentBaseClass& element )
    {
        return element.isPresent( name_ );
    }

    bool operator( const GetDataBaseClass& element )
    {
        const Data& data = element.getData();
        return data.isPresent( name_ );
    } 
 };

如果这种模式在不同的类类型中发生很多,并且在使用谓词之前就知道了类型,那么你可以模拟谓词本身。

e.g。

template<class T1, class T2>
struct Finder
{
    Finder( const std::string& name ):
        name_( name )
    {
    }

    bool operator( const T1& element )
    {
        return element.isPresent( name_ );
    }

    bool operator( const T2& element )
    {
        const Data& data = element.getData();
        return data.isPresent( name_ );
    } 
 };

或者您可以使用的另一种方法是使用某种类特征来保存信息。

e.g。

struct UseIsPresent
{
    template<class T>
    static bool CompareElement( const T& element, const std::string& name )
    {
        return element.isPresent( name );
    }
};

struct UseGetData
{
    template<class T>
    static bool CompareElement( const T& element, const std::string& name )
    {
        const Data& data = element.getData();
        return data.isPresent( name );
    } 
};

// default to using the isPresent method
template <class T>
struct FinderTraits
{
    typedef UseIsPresent FinderMethodType;
};

// either list the classes that use GetData method
// or use a common base class type, e.g. UseGetData
template <>
struct FinderTraits<UseGetData>
{
    typedef UseGetData FinderMethodType;
};

struct Finder
{
    Finder( const std::string& name )
    : name_( name )
    {
    }

    template<class T>
    bool operator()( const T& element )
    {
        return FinderTraits<T>::FinderMethodType::CompareElement<T>(element, name_);
    }

    std::string name_;
};

所有这些方法的缺点是,在某些时候你需要知道能够将它们分成哪种方法的类型。

其他提示

您可以查看 Veldhuizen的主页用于 switch 模板。您可以使用它来选择确切的运算符吗?

让您的类型来自“功能类型” (例如类型“has_function1”)将作为java接口使用,并且您有机会,因为SFINAE可用于测试是否可以将一种类型转换为另一种类型。

如果您有兴趣,我可以查看并给您更详细的答案。

编辑: 我知道你说你没有可用的Boost库,但是有什么东西阻止你获得boost :: is_convertible工作所需的几个文件吗?编译时没有特别的东西!

提升不是魔术;使用SFINAE非常简单:

    template< typename TElement >
    bool operator( const TElement& element, ... )
    {
        return element.isPresent( name_ );
    }

    template< typename TElement >
    bool operator( const TElement& element, const Data& data = element.getData())
    {
        return data.isPresent( name_ );
    }

如果不编译,SFINAE将删除第二个重载。重载分辨率将选择第二个,如果它编译,因为...是一个更糟糕的匹配。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top