我需要为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”的类位于“程序”命名空间中。
感谢。
答案 0 :(得分:3)
为什么要使用模板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_;
};
所有这些方法的缺点是,在某些时候你需要知道能够将它们分成哪种方法的类型。
答案 1 :(得分:1)
您可以查看switch
模板的Veldhuizen's homepage。您可以使用它来选择确切的运算符吗?
答案 2 :(得分:0)
让您的类型派生自“功能类型”(例如类型“has_function1”),它将作为Java接口使用并且您有机会,因为SFINAE可用于测试是否可以将一种类型转换为另一种类型。
如果您有兴趣,我可以查看并给您更详细的答案。
编辑: 我知道你说你没有可用的Boost库,但是有什么东西阻止你获得使boost :: is_convertible工作所需的几个文件吗?编译时没有特别的东西!
答案 3 :(得分:0)
提升不是魔术;使用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将删除第二个重载。重载分辨率将选择第二个,如果它编译,因为...是一个更糟糕的匹配。