试图理解重载函数是如何选择的
Trying to understand how an overloaded function is chosen
我有以下程序:
#include <iostream>
namespace detail {
template <class T> char test(int T::*)
{
std::cout << "Came to onen";
return 0;
}
template <class T> int test(...)
{
std::cout << "Came to twon";
return 0;
}
}
struct A {};
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
在使用g++ 4.8.2进行测试时,它产生以下输出:<>之前来到了一个到了二之前
我的问题是:为什么第一次调用明确选择detail::test
的第一个版本?
在没有details::test
的第一个版本的情况下,main
的代码编译得很好。当它在那里时,编译器认为它比第二个更适合detail::test<A>()
。
更新2
在阅读了之后,即使对于不完整类型或没有指定类型的成员,指向成员的指针也是格式良好的。,我试了下面的,它工作。
struct A;
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
c++ 11标准有相当多的地方揭示了我没有想到的概念。
编译器经历了名称查找、参数推导和重载解析的三位一体过程。名称查找发现test
的两个重载,并且指向成员的指针的参数推导对于非类类型将失败,但对于不完整类型或缺少成员则不会失败。最后,在可行的候选对象中,重载解析选择最佳匹配(省略号转换为最低等级)。
这里有三个相关的标准引号:
根据8.3.3指向成员的指针[dcl。mptr]/2指向成员的指针即使对于不完整类型或没有指定类型的成员也是格式良好的。
根据14.8.2模板实参演绎[temp. deduction]/8:
如果替换导致无效的类型或表达式,则键入扣除失败。
其中一个例子是:
最后,根据13.3.3.2对隐式转换序列[over.ics]进行排序。省略号试图在T不是类时创建"指向T成员的指针"类型。
(...)
重载在重载解析过程中具有所有隐式转换序列中最低的秩:
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);
在第一次重载时产生替换错误,因此选择第二个匹配项。
在本例中,第一个重载比第二个重载被选择,因为就参数转换序列而言,它更适合——省略号转换序列排在最后。
- 如何使用默认参数等选择模板专业化
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 选择要调用的构造函数
- C++选择排序算法中的逻辑错误
- QTreeView幻灯片多选后无法使用单击选择
- 无法获取菜单选择以运行函数.C++
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 在C++中,如何通过几种类型从元组中选择多个元素
- 讨论 - 创建矩阵时的数组与向量的向量 - 什么是最实用的选择
- 对可变参数使用声明.如何选择正确的功能
- 选择选举获胜者的程序
- 如何选择在 csv 文件中输出的位置
- 根据用户回答声明"Players"。用户选择玩家数量。播放器是结构体
- 程序在尝试猜测它选择的随机数时进入无限循环?
- 选择和修改嵌套向量中的条目的最佳实践
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 在运行时选择父类的实现
- 数数并选择 sqlite 中的前三名
- 列表视图更改选择颜色