使用enable_if对void参数成员方法进行条件编译

时间:2017-01-04 22:03:03

标签: template-meta-programming sfinae enable-if

#include <iostream>
#include <type_traits>

using namespace std;

template<typename T>
struct MyClass{

  void hello( void) {
    hello(std::is_same<T,bool>());
  }

   void hello(std::true_type){
     cout<<"hello only for bools"<<endl;
   }

};


int main(int argc, char** argv){

  MyClass<bool> myclass1;
  myclass1.hello();

  MyClass<float> myclass2;
  //myclass2.hello(); //throws error as it should

  return 0;
}

我在阅读enable_if method specialization后写了上面的代码。我希望hello()方法只有在模板参数是bool并且有效时才存在。但是,当我尝试使用enable_if解决相同的问题时,我遇到了问题。我有以下代码。任何帮助表示赞赏。如果enable_if不适合此作业,通常使用什么?

#include <iostream>
#include <type_traits>

using namespace std;

template<typename T>
struct MyClass{

  typename std::enable_if<std::is_same<T,bool>::value, void>::type
  hello(void)
  {
    cout<<"hello only for bools"<<endl;
  }
};

int main(int argc, char** argv){

  MyClass<bool> myclass1;
  myclass1.hello();

  MyClass<float> myclass2;// compilation error. Don't know how to solve
  //myclass2.hello(); //I want only this line to cause compilation error

  return 0;
}

编辑:我在std::enable_if to conditionally compile a member function的jpihl回答中找到了我的问题的解决方案。但有人可以解释为什么以上不起作用吗?

#include <iostream>
#include <type_traits>

using namespace std;

template<typename T>
struct MyClass{

  template<class Q = T>
  typename std::enable_if<std::is_same<Q, bool>::value, void>::type hello()
  {
    cout<<"hello only for bools"<<endl;
  }

};

int main(int argc, char** argv){

  MyClass<bool> myclass1;
  myclass1.hello();

  MyClass<float> myclass2;// throws errow. Don't know how to solve
  myclass2.hello(); //

  return 0;
}

1 个答案:

答案 0 :(得分:1)

enable_if的第一次尝试不起作用,因为SFINAE适用于重载决策 功能(或成员功能)模板,它将消除 当过载集合中的函数模板的特化 专业化无法编译。

第一次尝试时,成员hello不是成员函数模板。 它没有模板参数。它只是模板的成员功能

它的返回类型由enable_if表达式表达 如果模板参数T不是,则会引发编译失败 实例化为bool。这不会使成员自身成为模板。 SFINAE没有申请。一旦你宣布MyClass<float> myclass2,就会 MyClass<T>及其所有成员的专业化是完全确定的。 必须实例化该专业化的成员函数hello, 并且T = float尝试这样做必然无法编译。

在第二次成功尝试中,hello 成员函数模板( 一个类模板)。它有一个模板参数Q,默认情况下为= T。 因此,SFINAE适用,您可以按预期方式将其与enable_if一起使用。 您可以无误地声明MyClass<float> myclass2,因为这样做 不会强制模板成员MyClass<float>::hello<Q>

的任何实例化

由于您只编写了hello的一个重载,因此只有一个专门化 任何Q选择的成员函数模板。当Q = bool时,那 单一专业化存活,myclass1.hello()将存在 编译。当Q!= bool时,SFINAE会取消该单一专业化 并且myclass2.hello()无法编译。

生动地说明第二种情况下SFINAE如何在瞬间运行 成员函数模板,请考虑:

  MyClass<float> myclass2;
  myclass2.hello<bool>();

很好;而另一方面:

  MyClass<bool> myclass1;
  myclass1.hello<float>();

无法编译。

这是documentation of SFINAE