混合decltype和enable_if

Fle*_*exo 7 c++ c++11

似乎decltype与SFINAE一起使用enable_if并不简单.我尝试goenable_if三种不同的方式编写使用方法.所有这些都因编译器错误而失败(使用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;
}
Run Code Online (Sandbox Code Playgroud)

我可以看到问题是什么 - decltype需要在偶然enable_if有机会排除功能之前发生.剩下的问题是如何解决并获得类似的行为?是否有一种简单,通用的方法来做到这一点,而不是诉诸写作 has_thing特征使用enable_if

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

mfo*_*ini 6

如果go方法是模板方法,SFINAE将起作用:

template <typename T>
struct Test {
  template <class U = T>
  auto go() -> decltype(U::thing()) {
     return T::thing();
  }
};
Run Code Online (Sandbox Code Playgroud)

您也可以使用该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();
} 
Run Code Online (Sandbox Code Playgroud)

然后:

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

  b.go(); // Works!
  f.go(); // Fails!
}
Run Code Online (Sandbox Code Playgroud)