【发布时间】:2013-08-06 16:53:03
【问题描述】:
我多次成功使用 SFINAE。检测一个类是否提供函数不是问题。我目前的问题似乎与his problem相反!而不是also 检测派生方法,我更愿意检测only 类的方法。似乎与方法是模板有关。
是否可以检测类模板方法?我试图用一种不应该伤害的类型来实例化模板,但没有运气。
struct A { template<class T> void Func( T ) {}; };
struct B :A {};
template< class T >
struct CheckForFunc
{
typedef char(&YesType)[1];
typedef char(&NoType)[2];
template< class U, void (U::*)( int ) > struct Sfinae;
template< class T2 > static YesType Test( Sfinae<T2,&T2::Func>* );
template< class T2 > static NoType Test( ... );
static const bool value = sizeof(Test<T>(0))==sizeof(YesType);
};
int main(int argc, char* argv[])
{
// gives "1"
std::cout << "Value A=" << CheckForFunc< A >::value << std::endl;
// doesn't compile!
std::cout << "Value B=" << CheckForFunc< B >::value << std::endl;
return 0;
}
错误信息:
error: ‘&A::Func’ is not a valid template argument for type ‘void (B::*)(int)’ because it is of type ‘void (A::*)(int)’
请注意,此 SFINAE 非常适用于模板方法,但不适用于派生!不好的是它不仅检测到错误,而且编译失败。
如何在不使用“样本”类型(此处为 int)的情况下编写 SFINAE 测试?
编辑:抱歉,仅限 C++03! LLVM 很好用,还有 VS2008,只是 GCC 和 QNX 不行(我明天得看看版本)。
Edit2:不知道 Coliru!很酷,这里是error!
【问题讨论】:
-
为什么不直接使用
Test(void (T2::*)(int) = nullptr)和sizeof(Test<T>())? -
Your code compiles, using clang++。我觉得这很奇怪!我认为这是clang中的一个错误!
-
使用默认参数的有趣想法。 nullptr 是 C++11 吗?
-
实际的问题是
Sfinae<T2,&T2::Func>*是否会导致T2 == B的替换失败(后一种情况:代码无法编译)。我倾向于说它 is 替换失败,在这种情况下,clang++ 是对的,g++ 是错误的。正如 David Rodríguez 指出的那样,其背后的问题是模板参数的上下文中不允许从void (A::*)(int)转换为void (B::*)(int)。 -
@KerrekSB:这不会是对 T2::Func() 的测试,对吗? DyP:是的,似乎是问题所在,但是如何使用 GCC 进行测试?