读书人

有关函数模板与重载函数的调用优先级有

发布时间: 2013-09-06 10:17:17 作者: rapoo

有关函数模板与重载函数的调用优先级问题
在C++Primer上看模板特化时遇到的一个问题



为什么 我在codeblocks上运行是你想要的结果?
[解决办法]
vs2012的结果和LZ的一样。

仔细看了一下,感觉绑定到模板的要符合标准些,因为两者的conversion sequence都是
Standard conversion sequences。

这里的引用绑定属于identity conversion,其rank是Exact Match。
而调用普通函数时实参是数组类型,形参是指针类型,所以这里有array-to-pointer conversion和qualification conversions,两者的rank一样,最后的转换rank是Exact Match。

然而,仅比较rank,都是一样,无区别。但是在相同情况下,identity conversion优于非
indentity conversion,所以引用绑定的要优于后者。

还可以加个void func(char (&s)[10])玩一把。

[解决办法]
按这样分析的话,函数版本去掉const后,
the identity conversion sequence is considered to be a subsequence of any non-identity
conversion sequence


依然适用,还是应该使用模板版本,但gcc给的结果是函数版本,这得考察一下。

另外,前面说
“然而,仅比较rank,都是一样,无区别。但是在相同情况下,identity conversion优于非
indentity conversion,所以引用绑定的要优于后者。”

有点问题的,因为proper subsequence关系是在rank的比较之前。
[解决办法]
再补一刀:
the identity conversion sequence is considered to be a subsequence of any non-identity
conversion sequence

有个前提是excluding any Lvalue Transformation,所以,对于LZ的问题就是那个const引起了
S1 is a proper subsequence of S2规则的生效。

所以,如果去掉函数版本的const,应该选择模板,因为这个时候函数优先于模板的规则生效。

void func(char (&s)[10])和void func(char *s)接受char[10],则ambiguous。
void func(const char (&s)[10])和void func(const char *s)接受char[10],则选择前者(前者引用兼容属于identity conversion,后者属于qualification conversions)。
void func(const char (&s)[10])和void func(const char *s)接受const char[10],则ambiguous。

[解决办法]
楼上都说完了,主楼就是 identity conversion vs. array-to-pointer + qualification conversion, 前者是后者的 proper subsequence,所以选择模板的。

另外,我觉得标准在这块儿比较乱,不同的编译器很可能做出不同的解释。最好的做法就是别写这样的代码,免得移植的时候出莫名其妙的错误。

读书人网 >C++

热点推荐