我想编写一个模板函数来检查一些Timestamp属性(类继承自Timed
),但也必须适用于没有时间戳的类型。我找到的最好(也很难看)的解决方案如下:
class Timed {
protected:
int mTime;
public:
explicit Timed(int time=0): mTime(time){}
int getT() const {return mTime;}
};
template<typename T>
bool checkStale(T const* ptr) const {
return checkStaleImp(ptr, boost::is_base_of<Timed, T>() );
}
template<typename T>
template<bool b>
bool checkStaleImp(T const* ptr, boost::integral_constant<bool, b> const &){
return true;
}
template<typename T>
bool checkStaleImp(T const* ptr, boost::true_type const&){
const int oldest = 42;
return (42 <= ptr->getT());
}
这是一个功能的三个功能。是否有更简单的方法来实现这一目标,例如使用boost::is_base_of
或者......类似于if条件或boost :: enable if将函数输出转换为不是从Timed
派生的类的常量。遗憾的是,具有虚函数的解决方案不是一种选择。
答案 0 :(得分:5)
你可以用两个简单的重载和没有模板机制做同样的事情:
bool checkStale(void const* ptr){
return true;
}
bool checkStale(Timed const* ptr){
const int oldest = 42;
return (oldest <= ptr->getT());
}
无需在is_base_of
上发送代码。
答案 1 :(得分:3)
我认为这不是非常难看的解决方案,正如你所说的那样。但是,如果将辅助函数实现为本地类的静态成员,则可以减小辅助函数的范围:
template<typename T>
bool checkStale(T const* ptr) const
{
struct local
{
static bool checkStaleImp(T const* ptr, boost::false_type const &)
{
return true;
}
static bool checkStaleImp(T const* ptr, boost::true_type const&)
{
const int oldest = 42;
return (42 <= ptr->getT());
}
};
return local::checkStaleImp(ptr, boost::is_base_of<Timed, T>());
}
现在,有一个为用户公开的函数,以及本地类中的实际实现。
顺便说一句,在C ++ 11中,您可以使用std::is_base_of
而不是boost的版本。与std::true_type
和std::false_type
相同。
答案 2 :(得分:0)
使用enable_if
选择可能的重载。由于以下示例中使用的条件是互补的,因此始终只有一个可用的过载,因此没有歧义
template<typename T>
typename std::enable_if<std::is_base_of<Timed,T>::value,bool>::type
checkStale(T const *ptr) const {
const int oldest = 42;
return oldest <= ptr->getT();
}
template<typename T>
typename std::enable_if<!std::is_base_of<Timed,T>::value,bool>::type
checkStale(T const *ptr) const {
return true;
}