8

似乎decltype与 SFINAE 一起使用enable_if并不简单。我尝试以三种不同的方式编写gousing enable_if。它们都因编译器错误而失败(对于 GCC,字面意思是:“错误:'thing' 不是 '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;
}

我可以看到问题所在 -decltype需要在enable_if甚至有机会排除该功能之前发生。剩下的问题是如何解决并获得类似的行为?有没有一种简单、通用的方法来做到这一点,而无需 has_thingenable_if?

使用 G++ 4.7 和 clang++ 3.0 测试。

4

2 回答 2

6

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!
}
于 2012-07-02T11:55:41.827 回答
0

当然,您的 SFINAE 不起作用。该go函数不是模板,因此任何 SFINAE 都不能应用。除此之外,它应该可以正常工作decltype(您实际上不需要任何has_thing标志)。

例如。这很好用(并且可以很好地与其他重载一起使用):

template <class U>
auto go(Test<U> t)
  -> decltype(U::thing()) {
  return U::thing();
}
于 2012-07-02T11:51:12.373 回答