C++ 重载解析在添加模板参数时产生不明确的调用

C++ 重载解析在添加模板参数时产生不明确的调用,c++,c++11,c++14,C++,C++11,C++14,在下面的代码中,编译器可以成功地解析调用f()调用f(int&,const char*) 然而,对g()的调用是不明确的。它将所有四个重载列为可能的重载集。如果我从数组参数的模板参数列表中删除、typename T2、std::size\u t I,并对它们进行硬编码,则不会出现歧义,编译器会选择g(t&,const char*) 为什么添加两个模板参数会使其变得模棱两可?我可以看到,尽管衰变和强制转换,它如何解决任何一个重载,但我无法理解添加这些模板参数是如何引入歧义的 我已经在Clang3.

在下面的代码中,编译器可以成功地解析调用
f()
调用
f(int&,const char*)

然而,对
g()
的调用是不明确的。它将所有四个重载列为可能的重载集。如果我从数组参数的模板参数列表中删除
、typename T2、std::size\u t I
,并对它们进行硬编码,则不会出现歧义,编译器会选择
g(t&,const char*)

为什么添加两个模板参数会使其变得模棱两可?我可以看到,尽管衰变和强制转换,它如何解决任何一个重载,但我无法理解添加这些模板参数是如何引入歧义的

我已经在Clang3.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;
}
#包括
void f(int&,const char*){}
void f(int&,char(&)[8]){
void f(int&,bool){}
void f(int&,const std::string&){
模板
void g(T&,bool){}
模板
void g(T&,const char*){}
模板
void g(T&,const std::string&){
模板
空g(T&,T2(&)[I]){
int main(int argc,char*argv[])
{
int i=1;
f(i)“”;
g(i)“”;
返回0;
}
过载#2:

过载#4:

模板
空g(T&,T2(&)[I]){
当使用字符串文本调用
g(…)
时,重载#2和重载#4将是不明确的;字符串文字参数将被推导为
const char*
以及
T2(&)[I]

原因


您的字符串literal
const char[8]
,这清楚地显示了它是如何被推断为重载4的。然而,由于数组会衰减为指针,
const char[8]
也是
const char*
,这清楚地推断为重载#2。

编译器通常会列出所有可能的重载,而不仅仅是不明确的重载。因此,重载1和重载3没有歧义。它们是二等品。但是,重载2和重载4是一阶的-字符串文字是数组,数组衰减也是一阶的

你说得对。我错过了数组重载中的
const
void g(T&, const char*){}
template <typename T, typename T2, std::size_t I>
void g(T&, T2(&)[I]){}