gcc vs. clang,msvc和icc:这个函数调用不明确吗?

Rum*_*rak 9 c++ partial-ordering language-lawyer c++11

我能得到的所有编译器都同意这很好:

template <typename Check, typename... T>
auto foo(Check, T...) -> void;

template <typename... T>
auto foo(int, T...) -> void;

int main()
{
  foo(7, "");
}
Run Code Online (Sandbox Code Playgroud)

但是,根据gcc,以下代码(具有无法从函数参数推导出的前导模板参数)是不明确的:

template <typename X, typename Check, typename... T>
auto bar(Check, T...) -> void;

template <typename X, typename... T>
auto bar(int, T...) -> void;

int main()
{
  bar<void>(7, ""); // ambiguous according to gcc
  bar<void>(7);     // just fine
}
Run Code Online (Sandbox Code Playgroud)

另一方面,clang,msvc和icc对此非常满意.

哪个编译器是对的?

参考标准的各个部分是优选的.

Col*_*mbo 4

这是核心问题200

14.5.6.2 [temp.func.order]第 3-5 段中如何确定模板函数的部分排序的描述没有对非推导的模板参数做出任何规定。例如,以下代码中的函数调用是不明确的,即使一个模板“显然”比另一个模板更专业:

template <class T> T f(int);
template <class T, class U> T f(U);
void g() {
    f<int>(1);
}
Run Code Online (Sandbox Code Playgroud)

原因是两个函数参数列表都不允许T推导模板参数;两种推导都失败,因此两个模板都不被认为比另一个模板更专业,并且函数调用不明确。

核心问题 214的解决方案(该问题被简化为)引入了[temp.deduct.partial]/11

在大多数情况下,所有模板参数都必须具有值才能成功推导,但出于部分排序的目的,只要模板参数未在用于部分排序的类型中使用,模板参数就可以保持没有值

显然,一旦包发挥作用,GCC 对这种措辞的实现就会出现错误。