R S*_*ahu 4 c++ templates g++ overload-resolution c++11
我有以下程序:
#include <iostream>
namespace detail {
template <class T> char test(int T::*)
{
std::cout << "Came to one\n";
return 0;
}
template <class T> int test(...)
{
std::cout << "Came to two\n";
return 0;
}
}
struct A {};
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
使用g ++ 4.8.2进行测试时,会产生以下输出:
Came to one Came to two
我的问题:为什么第detail::test一个电话会明确选择第一个版本?
更新
在没有第一个版本的情况下details::test,main编译好的代码.当它存在时,编译器认为它detail::test<A>()比第二个更好.
更新2
在阅读了关于成员的指针之后,即使对于不完整类型或没有指定类型的成员,也是格式良好的.,我尝试了以下,它的工作原理.
struct A;
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
C++ 11标准有很多地方可以发现我不会想到的概念.
Tem*_*Rex 10
编译器经历名称查找,参数推导和过载解析的三位一体.名称查找找到两个重载test,并且对于非类类型,对成员的指针的参数推断将失败,但对于不完整类型或缺少成员则不会.最后,在可行的候选者中,重载决策选择最佳匹配(省略号转换是最低级别).
这里有三个相关的标准报价:
根据8.3.3成员指针[dcl.mptr]/2中的示例,即使对于不完整类型或没有指定类型的成员,指向成员的指针也是良好的.
根据14.8.2模板参数演绎[temp.deduct]/8:
如果替换导致无效的类型或表达式,则类型推导失败.
列出的众多例子之一是:
当T不是类类型时,尝试创建"指向T成员的指针".
最后,根据13.3.3.2对隐式转换序列进行排名[over.ics.rank],省略号(...)重载在重载解析期间具有所有隐式转换序列的最低等级:
2比较隐式转换序列的基本形式(如13.3.3.1中所定义)
- 标准转换序列(13.3.3.1.1)是比用户定义的转换序列或省略号转换序列更好的转换序列,并且
- 用户定义的转换序列(13.3.3.1.2)是比省略号转换序列(13.3.3.1.3)更好的转换序列.
你的第一个电话detail::test<A>(0);有两个可行的候选人,但它选择了第一个超载,因为它是一个更好的匹配.第二个调用detail::test<int>(0);在第一个重载时给出了一个替换错误,因此选择了第二个匹配.