添加模板参数时,重载分辨率会产生模糊调用

时间:2015-09-29 20:51:44

标签: c++ c++11 c++14

在以下代码中,编译器可以成功解析对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;
}

2 个答案:

答案 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是第一顺序 - 字符串文字是一个数组,数组衰减也是第一顺序。