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

conditional compilation of void argument member method using 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;
}

编辑:我在 jpihl 在 std::enable_if to conditionally compile a member function 的回答中找到了问题的解决方案。但是谁能解释为什么上面的方法不起作用?

#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;
}

您对 enable_if 的第一次尝试无效,因为 SFINAE 应用于重载解析 函数(或成员函数)templates,它将消除 来自重载集的函数模板的特化 专业化无法编译。

在您的第一次尝试中,成员 hello 不是成员函数 template。 它没有模板参数。它只是 class 模板的成员 function

它的 return 类型由 enable_if 表达式表示 如果 class 模板参数 T 不是,将导致编译失败 实例化为 bool。这不会使成员函数本身变成模板。 SFINAE 没有申请。一旦你声明 MyClass<float> myclass2MyClass<T> 及其所有成员的专业化已完全确定。 该特化 的成员函数 hello 必须 实例化, 并且 T = float 这样做的尝试肯定无法编译。

在第二次成功的尝试中,hello 一个成员函数模板(的 class 模板)。它有一个模板参数,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