考虑以下代码:
#include<iostream>
template<class..., class... T>
int f(T...) { return 1; }
template<class... T>
int f(T...) { return 2; }
int main()
{
std::cout << f(1);
}
它编译并打印1
在 gcc 8.2 上,但由于调用而无法在 clang 7 上编译f(1)
模棱两可。
如果调用被替换为f()
两个编译器都无法编译,声称调用不明确。
如果参数包class... T
被替换为一个简单的参数class T
(and T...
with T
),两个编译器也都声称存在歧义。
第一个示例中哪个编译器符合标准?我想这可以归结为函数模板的特定部分排序规则,或者以这种方式使用双参数包是否已经格式错误?
Edit:
我的理解是,双包本身并不是格式错误的,因为在我的阅读中,如果第二个包可以从函数参数中推导出来, [temp.param] 17.1/15 似乎明确允许这种情况,这似乎是因为这T...
函数参数包。
还可以显式指定第一个参数包的参数,但不能显式指定第二个参数包的参数,因此并不总是出现(在模板参数推导之后)至少一个参数包为空的情况。我不确定这是否会使程序格式错误,因为我不知道如何阅读,例如[temp.res] 17.7/8.3 在这种情况下。
gcc 和 clang 似乎都适合双参数包本身,例如当第二个函数模板重载被删除时,两个编译器都会打印1
。但这可能是一个情况格式错误,无需诊断.
此外,我假设通过类模板参数推导,可变参数类模板可以定义可变参数构造函数模板,这意味着类似于我的双参数包示例的构造函数候选者,并且据我了解,相同的重载解析和模板参数推导需要放在那个背景下。这个问题是由具有这种设置的另一个问题引发的:可变参数类模板推导在 gcc 8.2 中失败,用 clang 和 msvc 编译 https://stackoverflow.com/questions/53356903/variadic-class-template-deduction-fails-with-gcc-8-2-compiles-with-clang-and-ms另请参阅对此的讨论:推导指南和带有可变参数模板构造函数的可变参数类模板 - 参数包长度不匹配 https://stackoverflow.com/questions/43430921/deduction-guides-and-variadic-class-templates-with-variadic-template-constructor
现在我也找到了问题的答案推导指南和可变参数模板 https://stackoverflow.com/questions/44338584/deduction-guide-and-variadic-templates我认为这意味着 gcc 是错误的,并且调用应该被认为是不明确的,但我想验证一下这是否同样适用于这里。我也欢迎更详细的推理,因为函数模板部分排序规则对我来说似乎非常不清楚。