阅读马蒂厄的回答后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 的主要问题是您将 run-time 引用用作 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, 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>(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;
}
关于c++ - SFINAE decltype 逗号运算符技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18265536/