我不明白这段代码是如何工作的。谁能告诉我一点。我非常确定“参数包应该是最后一个参数”
void foo(auto&&...args1, auto&&... args2, auto&&... args3) {
std::cout << "args1:\n", ((std::cout << args1 << " "), ...);
std::cout << "args2:\n", ((std::cout << args2 << " "), ...);
std::cout << "args3:\n", ((std::cout << args3 << " "), ...);
}
int main(int argc, char** argv)
{
foo(1,2,3,4,5,6);
}
Run Code Online (Sandbox Code Playgroud)
如果允许,我如何拆分arg1、args2和args3?
编译器 (g++-11) 假定除 args3 之外的所有参数包均为空,因此输出为
args1:
args2:
args3:
1 2 3 4 5 6
Run Code Online (Sandbox Code Playgroud) 请考虑以下代码:
#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);
}
Run Code Online (Sandbox Code Playgroud)
它1在gcc 8.2上编译和打印,但由于调用f(1)不明确而无法在clang 7上编译.
如果调用被替换为f()两个编译器都无法编译声称调用是不明确的.
如果参数包class... T被以简单的参数替换class T(和T...与T),二者编译器也要求歧义.
在第一个示例中,哪个编译器符合标准?我想这归结为功能模板的特定部分排序规则,还是以这种方式使用双参数包已经形成错误了?
编辑:
我的理解是双包本身并不是格式错误,因为我的阅读中的[temp.param] 17.1/15似乎明确允许这个,如果第二个包可以从函数参数中推导出来,这似乎是因为该T...函数参数包.
也可以显式指定第一个参数包的参数,但不是第二个参数包的参数,因此并不总是(在模板参数推断之后)至少一个参数包为空.我不确定这是否会使程序格式不正确,因为我不知道在这种情况下如何阅读例如[temp.res] 17.7/8.3.
gcc和clang似乎都没有双参数包本身,例如当第二个函数模板重载被删除时,两个编译器都打印1.但这可能是形成不良的情况,无需诊断.
此外,我假设使用类模板参数推导,可变参数类模板可以定义一个可变参数构造函数模板,这意味着构造函数候选类似于我的双参数包示例,据我所知,相同的重载决议和模板参数推导需要在这种情况下.这个问题是由另一个带有这样设置的问题所驱动的:Variadic类模板推导失败,使用gcc 8.2,编译clang和msvc 另请参阅讨论:使用可变参数模板构造函数的演绎指南和可变参数类模板 - 不匹配的参数包长度
现在我也找到了问题的演绎指南和可变参数模板的答案,我假设gcc是错误的并且调用应该被认为是模棱两可的,但我想让它验证这适用于这里同样的方式.我也会更加详细地欢迎推理,因为功能模板偏序规则对我来说似乎很不清楚.
c++ language-lawyer overload-resolution template-argument-deduction