似乎将decltype
与SFINAE enable_if
一起使用并不简单。我尝试以三种不同的方式使用go
编写enable_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;
}
我可以看到问题是什么 - decltype
需要在enable_if
甚至有机会排除该功能之前发生。剩下的问题是如何解决并获得类似的行为?是否有一种简单,通用的方法来执行此操作而无需在has_thing
中编写enable_if
特征?
使用G ++ 4.7和clang ++ 3.0进行测试。
答案 0 :(得分: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!
}
答案 1 :(得分:0)
当然你的SFINAE不起作用。 go
函数不是模板,因此不能应用任何SFINAE。除此之外它应该与decltype
一起正常工作(你实际上不需要任何has_thing
标志)。
EG。这工作正常(并与其他重载很好地一起使用):
template <class U>
auto go(Test<U> t)
-> decltype(U::thing()) {
return U::thing();
}