Fai*_*ali 23 c++ templates sfinae overload-resolution c++11
在C++ 0x中,简化了SFINAE规则,使得在演绎的"直接上下文"中出现的任何无效表达式或类型不会导致编译器错误,而是导致演绎失败(SFINAE).
我的问题是:
如果我采用重载函数的地址并且无法解决,那么在演绎的直接上下文中是否会失败?
(如果它无法解决,那么它是一个硬错误还是SFINAE)?
以下是一些示例代码:
struct X
{
// template<class T> T* foo(T,T); // lets not over-complicate things for now
void foo(char);
void foo(int);
};
template<class U> struct S
{
template<int> struct size_map
{ typedef int type; };
// here is where we take the address of a possibly overloaded function
template<class T> void f(T,
typename size_map<sizeof(&U::foo)>::type* = 0);
void f(...);
};
int main()
{
S<X> s;
// should this cause a compiler error because 'auto T = &X::foo' is invalid?
s.f(3);
}
Run Code Online (Sandbox Code Playgroud)
Gcc 4.5声明这是一个编译器错误,并且clang吐出一个断言违规.
以下是一些更感兴趣的相关问题:
FCD-C++ 0x是否清楚地指明了这里应该发生什么?
编译器拒绝此代码是错误的吗?
扣除的"直接背景"是否需要更好地定义?
谢谢!
Joh*_*itb 29
template<class T> void f(T,
typename size_map<sizeof(&U::foo)>::type* = 0);
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为U不参与演绎.虽然U是一种依赖类型,但在推断f它时,它被视为拼写为非独立名称的固定类型.您需要将其添加到参数列表中f
/* fortunately, default arguments are allowed for
* function templates by C++0x */
template<class T, class U1 = U> void f(T,
typename size_map<sizeof(&U1::foo)>::type* = 0);
Run Code Online (Sandbox Code Playgroud)
所以在你的情况下因为U::foo不依赖于f它自己的参数,你会在隐式实例化时收到错误S<X>(尝试注释掉调用,它仍然应该失败).FCD说14.7.1/1
类模板特化的隐式实例化会导致类成员函数,成员类,静态数据成员和成员模板的声明的隐式实例化,而不是定义或默认参数的实例化.
也就是说,如果您隐式实例化S<X>以下函数模板声明将被实例化
template<class T> void S<X>::f(T,
typename size_map<sizeof(&X::foo)>::type* = 0);
Run Code Online (Sandbox Code Playgroud)
然后分析该模板声明将发现它无法解析引用X::foo和错误输出.如果添加U1,模板声明将不会尝试解析对U1::foo(因为U1是参数f)的引用,因此在f尝试调用时将保持有效和SFINAE .