c – 混合decltype和enable_if

似乎使用带有SFINAE enable_if的decltype并不简单.我尝试用三种不同的方式使用enable_if编写go.所有这些都因编译器错误而失败(使用GCC字面意思:“错误:’事物’不是’foo’的成员”和实例化上下文).
#include <type_traits>

struct foo {
  enum { has_thing = false };
};

struct bar {
  enum { has_thing = true };
  static int thing() { return 0; }
};

template <typename T>
struct Test {
  /*auto go(typename std::enable_if<T::has_thing,int>::type=0) 
  -> decltype(T::thing()) {
    return T::thing();
  }*/

  /*typename std::enable_if<T::has_thing,decltype(T::thing())>::type go() {
    return T::thing();
  }*/

  template <bool B=T::has_thing,typename std::enable_if<B,int>::type = 0>
  auto go() -> decltype(T::thing()) {
     return T::thing();
  }
};

int main() {
  Test<bar> b;
  Test<foo> f;
}

我可以看到问题是什么 – 在enable_if甚至有机会排除该函数之前需要发生decltype.剩下的问题是如何解决并获得类似的行为?是否有一种简单,通用的方法来执行此操作而无需在enable_if中编写has_thing trait?

使用G 4.7和clang 3.0进行测试.

解决方法

如果go方法是模板方法,则SFINAE将起作用:
template <typename T>
struct Test {
  template <class U = T>
  auto go() -> decltype(U::thing()) {
     return T::thing();
  }
};

你也可以使用has_thing值,但是没有必要这样做,因为SFINAE将在上面的例子中处理它:

template <class U = T,typename std::enable_if<U::has_thing,int>::type = 0>
auto go() -> decltype(U::thing()) {
   return T::thing();
}

然后:

int main() {
  Test<bar> b;
  Test<foo> f;

  b.go(); // Works!
  f.go(); // Fails!
}

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...