在以下代码中,编译器可以成功解析对f()
的呼叫以呼叫f(int&, const char*)
。
然而,对g()
的调用含糊不清。它列出了所有四个重载作为可能的过载集。如果我从数组参数的模板参数列表中删除, typename T2, std::size_t I
,并对其进行硬编码,则没有歧义,编译器会选择g(T&, const char*)
。
如何添加两个模板参数会使这种模糊不清?我可以看到,虽然衰减和转换,它可以解决任何一个重载,但我无法弄清楚添加这些模板参数如何引入歧义。
我在Clang 3.8(未发布)和VC ++ 2015上进行了测试。
#include <string>
void f(int&, const char*){}
void f(int&, char(&)[8]){}
void f(int&, bool){}
void f(int&, const std::string&){}
template <typename T>
void g(T&, bool){}
template <typename T>
void g(T&, const char*){}
template <typename T>
void g(T&, const std::string&){}
template <typename T, typename T2, std::size_t I>
void g(T&, T2(&)[I]){}
int main(int argc, char* argv[])
{
int i = 1;
f(i, " ");
g(i, " ");
return 0;
}
答案 0 :(得分:1)
超载#2:
void g(T&, const char*){}
超载#4:
template <typename T, typename T2, std::size_t I>
void g(T&, T2(&)[I]){}
使用字符串文字调用g(...)
时,重载#2和重载#4将不明确;字符串文字参数将推导为const char*
以及T2(&)[I]
。
<强>原因强>
您的字符串文字" "
为const char[8]
,清楚地显示了如何推断它超载#4。但是,由于数组衰减为指针,const char[8]
也是const char*
,这显然会导致超载#2。
答案 1 :(得分:1)
编译器通常会列出所有可能的重载,而不仅仅是模糊的重载。因此,重载1和3没有歧义。它们是二阶的。但是,重载2和4是第一顺序 - 字符串文字是一个数组,数组衰减也是第一顺序。