【问题标题】:conditional compilation of void argument member method using enable_if使用 enable_if 对 void 参数成员方法进行条件编译
【发布时间】:2017-01-04 22:03:02
【问题描述】:

.

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

【问题讨论】:

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


    【解决方案1】:

    您对enable_if 的第一次尝试不起作用,因为 SFINAE 适用于重载解决方案 函数(或成员函数)模板,它将消除 重载集中的函数模板的特化,当 特化无法编译。

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

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

    第二次尝试成功,hello成员函数模板(属于 类模板)。它有一个模板参数Q,默认为=T。 所以 SFINAE 适用,您可以以预期的方式与enable_if 一起使用它。 您可以毫无错误地声明MyClass&lt;float&gt; myclass2,因为这样做 不强制对模板成员 MyClass&lt;float&gt;::hello&lt;Q&gt; 进行任何实例化

    因为你只写了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

    【讨论】:

    • @user2709349 欢迎来到 Stackoverflow!在这里表示感谢的方式是通过勾选灰色复选标记accept the answer
    猜你喜欢
    • 2011-10-21
    • 2018-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多