c++ - 从重载模板函数中进行选择的规则是什么?

标签 c++ templates

给定下面的代码,为什么选择了 foo(T*) 函数?

如果我删除它(foo(T*)),代码仍然可以编译并正常工作,但是 G++ v4.4.0(可能还有其他编译器)将生成两个 foo () 函数:一个用于 char[4],一个用于 char[7]。

#include <iostream>
using namespace std;

template< typename T >
void foo( const T& )
{
    cout << "foo(const T&)" << endl;
}

template< typename T >
void foo( T* )
{
    cout << "foo(T*)" << endl;
}

int main()
{
    foo( "bar" );
    foo( "foobar" );
    return 0;
}

最佳答案

正式地,当比较转换序列时,左值转换被忽略。转换分为几个类别,例如资格调整(T* -> T const*)、左值转换 (int[N] -> int*, void() -> void(*)()) , 和别的。

两个候选人之间的唯一区别是左值转换。字符串文字是转换为指针的数组。第一个候选者通过引用接受数组,因此不需要左值转换。第二个候选者需要左值转换。

因此,如果有两个候选函数模板专门化通过仅查看转换同样可行,那么规则是通过对两者进行部分排序来选择更专门化的一个。

让我们通过查看函数参数列表的签名来比较两者

void(T const&);
void(T*);

如果我们为第一个参数列表选择一些独特的类型 Q 并尝试与第二个参数列表匹配,我们正在将 QT*。这将失败,因为 Q 不是指针。因此,第二个至少与第一个一样专业。

如果我们反过来,我们将 Q*T const& 进行匹配。删除引用并忽略顶层限定符,剩余的 T 变为 Q*。这是出于偏序目的的精确匹配,因此第二个转换后的参数列表对第一个候选的推导成功。由于另一个方向(反对第二个方向)没有成功,第二个候选者比第一个更多专门化 - 因此,如果存在歧义,重载解析将更喜欢第二个。

13.3.3.2/3:

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if [...]

  • S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that [...]

然后 13.3.3/1

  • let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then [...]

  • F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.5.2, or, if not that, [...]

最后,这是可能参与 13.3.3.1.1/3 标准转换序列的隐式转换表。

Conversion sequences http://img259.imageshack.us/img259/851/convs.png

关于c++ - 从重载模板函数中进行选择的规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1177739/

相关文章:

c++ - 如何使用 Boost 在 C++ 中通过上下文切换执行两个任务

c++ - reinterpret_cast 什么时候修改位?

c++ - 使用 HLSL 进行帧旋转

重载运算符时出现 C++ 函数模板偏特化错误

c++ - 自定义迭代器运算符重载

c++ - 如何制作大量类似的可执行文件

c++ - 模板类的大小

c++ - 随机访问迭代器 : What am I missing?

c++ - 没有可用于带有初始值设定项的静态常量成员的定义?

c++ - 比较 boost::optional<T&> 和 const T&