首页 > 解决方案 > 如何为特定类型专门化模板类方法?

问题描述

我有这样的代码:

class Bar {
 public:
  void print() {
    std::cout << "bar\n";
  }
};

template<typename T>
class Foo {
 public:
  template <typename std::enable_if<std::is_base_of<T,Bar>::value,T>::type>
  void print() {
    t.print();
  }

 template <typename>
  void print() {
    std::cout << t << std::endl;
  }
 private:
  T t;
};

int main() {
//  Foo<int> foo1;
  Foo<Bar> foo2;
  foo2.print();
}

这段代码的目的是:如果T t是 的一个Bar或一个子类Bar,则foo.print()推断为void print() {t.print();},否则推断为void print() {std::cout << t << std::endl;},但事情并没有像我预期的那样工作。编译器错误:

"一个非类型模板参数不能有类型'typename std::enable_if::value, Bar>::type' (aka 'Bar')",

这段代码有什么问题?

标签: c++c++11compiler-errorssfinaetemplate-specialization

解决方案


  1. 您应该print()对函数模板进行重载(以使SFINAE工作),否则始终首选非模板函数。

  2. 您应该让其print()采用自己的模板类型参数;不应该T直接对类模板参数进行类型检查,函数模板重载解析和 SFINAE 是对函数模板本身进行的,类模板不参与。

  3. 您可以将部分移动std::enable_if到返回类型。

  4. 如果您希望类型为或 的派生类,则应将指定的顺序更改为std::is_base_of(即std::is_base_of<Bar, X>不是) 。std::is_base_of<X, Bar>BarBar

例如

template <typename X = T>
typename std::enable_if<std::is_base_of<Bar, X>::value>::type print() {
  t.print();
}

template <typename X = T>
typename std::enable_if<!std::is_base_of<Bar, X>::value>::type print() {
  std::cout << t << std::endl;
}

居住


推荐阅读