c – 为什么第一个函数调用绑定到第一个函数?

参见英文答案 > Why does pointer decay take priority over a deduced template?1
为什么第一个函数调用(cm(car);)绑定到第一个函数

我明白,第二次调用是第二个函数,因为它是非模板,尽管是完美的匹配.

如果第一个函数被定义为具有固定数组长度的非模板,则为:

void cm(const char (&h)[8]) {cout << "const char (&)[8]" << endl;}

比再次被选中的第二个(第二个调用将是模糊的那种方式).

码:

template<size_t N> void cm(const char (&h)[N]) 
    {std::cout << " const (&)[N] " << endl;}

void cm(const char * h)
    {cout << " const char * " << endl;}

int main()
{
    char car[] = "errqweq";
    const char ccar[] = "errqweq";
    cm(car);
    cm(ccar);
}

输出

const (&)[N]
 const char *

解决方法

一个调用选择功能模板专门化 – 因为它是一个更好的匹配.
让我们标记两个重载:
template<size_t N> void cm(const char (&h)[N])  // (1) - the specialization
    {std::cout << " const (&)[N] " << endl;}

void cm(const char * h)                         // (2)
    {cout << " const char * " << endl;}

对于(1),汽车绑定到参考.这是一个身份转换1.
对于(2),在数组到指针转换后,产生char * 2,必须完成资格转换,所以char *变成char const *.现在正在调用这个:

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,
  • […]

数组到指针的转换是一个Lvalue Transformation,所以在这里不会被考虑 – 就像第二个例子一样.资格转换有自己的类别:资格调整.因此,转换为(1)的参数是转换为(2)参数的子序列:第一个是身份转换,第二个是资格转换,根据上述段落,身份转换是任何非身份转换.所以选择(1).

正如你已经提到过的,在第二种情况下,转换同样好;上述引用不起作用,因为转换为(2)s参数不是转换为(1)的参数的子序列.因此,[over.match.best] / 1适用.

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

  • for some argument j,ICSj(F1) is a better conversion sequence than ICSj(F2),or,
  • the context is an initialization by user-defined conversion […],
  • F1 is a non-template function and F2 is a function template specialization,

所以(2)选择一个.如果函数模板不是模板,而是具有参数char const(&)[8]的函数,那么调用将是不明确的as Clang correctly says.

1 [over.ics.ref] / 1:

When a parameter of reference type binds directly (8.5.3) to an
argument expression,the implicit conversion sequence is the identity
conversion
,unless the argument expression has a type that is a
derived class of the parameter type,in which case the implicit
conversion sequence is a derived-to-base Conversion (13.3.3.1).

[dcl.init.ref] / 5(在8.5.3中):

In all cases except the last (i.e.,creating and initializing a
temporary from the initializer expression),the reference is said to
bind directly to the initializer expression.

2 [conv.array]:

An lvalue or rvalue of type “array of N T” or “array of unkNown
bound of T” can be converted to a prvalue of type “pointer to T”.
The result is a pointer to the first element of the array.

T可以是cv合格的,所以被指派的类型也是.这里T只是char,所以指针的类型指向char =>字符*.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...