带有两个参数包的函数模板重载解析

2024-02-27

考虑以下代码:

#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 是错误的,并且调用应该被认为是不明确的,但我想验证一下这是否同样适用于这里。我也欢迎更详细的推理,因为函数模板部分排序规则对我来说似乎非常不清楚。


这里有两个问题。


First, [温度扣除部分]/12 https://timsong-cpp.github.io/cppwp/temp.deduct.partial#12(我也引用这个例子,因为它与你的相似)说:

在大多数情况下,如果并非所有模板参数都有值,则推导会失败,但出于部分排序的目的,如果模板参数未在用于部分排序的类型中使用,则模板参数可能会保持没有值。 [ 注意:在非推导上下文中使用的模板参数被视为已使用。 — 尾注 ] [ 示例:

template <class T> T f(int);            // #1
template <class T, class U> T f(U);     // #2
void g() {
  f<int>(1);                            // calls #1
}

—《示例结束》]

用于部分排序的类型是T...根据[温度扣除部分]/3 https://timsong-cpp.github.io/cppwp/temp.deduct.partial#3:

用于确定排序的类型取决于完成部分排序的上下文:

  • 在函数调用的上下文中,使用的类型是函数调用具有参数的函数参数类型。

  • ...

所以第一个未命名模板参数包class...不影响部分排序的结果。由于这两个函数模板没有其他差异,因此两者都不比另一个更专业,从而导致调用不明确。

This may与...有联系错误 49505 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49505 of GCC.


其次,即使第二个函数模板不存在,调用仍然应该是格式错误的。根据[临时参数.显式]/3 https://timsong-cpp.github.io/cppwp/temp.arg.explicit#3:

... A trailing未以其他方式推导的模板参数包将被推导为模板参数的空序列...

Only trailing模板参数包可以推导为空包,而第一个未命名模板参数包class...不是一个trailing模板参数包。

海湾合作委员会 (错误 69623 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69623) 和 铿锵 (错误 26435 https://bugs.llvm.org/show_bug.cgi?id=26435)有这个问题的错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有两个参数包的函数模板重载解析 的相关文章

随机推荐