根据参数类型制作模板功能代码的最简单方法是什么

时间:2012-02-07 16:28:54

标签: c++ templates boost sfinae

我想编写一个模板函数来检查一些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派生的类的常量。遗憾的是,具有虚函数的解决方案不是一种选择。

3 个答案:

答案 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_typestd::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;
}