阅读Matthieu的答案
here后,我决定自己尝试一下.
我的尝试无法编译,因为SFINAE不会踢入并剔除尝试访问T :: foo的has_foo函数.
error: ‘struct Bar’ has no member named ‘foo’
我错过了什么,还是我试图以这种方式不可能?
(我使用gcc-4.7.2)
完整的例子如下:
#include <iostream> // culled by SFINAE if foo does not exist template<typename T> constexpr auto has_foo(T& t) -> decltype((void)t.foo,bool()) { return true; } // catch-all fallback for items with no foo constexpr bool has_foo(...) { return false; } //----------------------------------------------------- template<typename T,bool> struct GetFoo { static int value(T& t) { return t.foo; } }; template<typename T> struct GetFoo<T,false> { static int value(T&) { return 0; } }; //----------------------------------------------------- template<typename T> int get_foo(T& t) { return GetFoo<T,has_foo(t)>::value(t); } //----------------------------------------------------- struct Bar { int val; }; int main() { Bar b { 5 }; std::cout << get_foo(b) << std::endl; return 0; }
解决方法
这里的主要问题是AFAICS是使用运行时引用作为constexpr函数参数.更换这个工作很好.
#include <iostream> // culled by SFINAE if foo does not exist template<typename T> constexpr auto has_foo(int) -> decltype(std::declval<T>().foo,bool()) { return true; } // catch-all fallback for items with no foo template<typename T> constexpr bool has_foo(...) { return false; } //----------------------------------------------------- template<typename T,has_foo<T>(0)>::value(t); } //----------------------------------------------------- struct Bar { int val; }; struct Foo { int foo; }; int main() { Bar b { 5 }; Foo f { 5 }; std::cout << get_foo(b) << std::endl; std::cout << get_foo(f) << std::endl; return 0; }