首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么是多变量args的函数?

什么是多变量args的函数?
EN

Stack Overflow用户
提问于 2022-10-28 09:47:56
回答 3查看 405关注 0票数 10

我不明白这段代码是如何工作的。有人能给我一点启发吗。我很确定“参数包应该是最后一个参数”

代码语言:javascript
运行
复制
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);
}

如果允许的话,我如何分割arg1、args2和args3?

编译器(g++-11)假定除args3之外的所有参数包都是空的,因此输出是

代码语言:javascript
运行
复制
args1:
args2:
args3:
1 2 3 4 5 6
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-10-28 13:28:23

这个程序是格式不良的,gcc和clang在接受代码方面是错误的.您也可以通过稍微修改代码来确认这一点,如下所示。这里也有一个旧的gcc虫

基本上,在函数模板(在下面所示的修改程序中)允许多个模板参数包的情况下,只要在模板参数包后面的每个模板参数都有一个默认值,或者可以推导它。但是,由于T2T3都不满足这些需求(因为它们不能明确推导并且不能具有默认参数),所以程序的格式是错误的。

同样的推理也适用于给定的示例,因为foo(在原始示例中)是一个泛型函数(也称为缩写函数模板)。

GCC和Clang对以下修改程序显示了相同的错误行为:演示

代码语言:javascript
运行
复制
template<typename... T1, typename... T2, typename... T3>
void foo(T1&&...args1, T2&&... args2, T3&&... 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); //gcc and clang compiles this while msvc correctly rejects this
}

下面是gcc的错误:

GCC接受包含多个模板参数包的无效程序

下面是clang bug:

Clang接受包含多个模板参数包的无效程序。

temp.param也可以看到同样的情况。

函数模板的模板参数包不应后面跟着另一个模板参数,除非该模板参数可以从函数模板的参数类型列表(dcl.fct)中推导出来,或者具有默认参数 (temp.deduct)。 // U既不能从参数类型列表中推导,也不能从指定的template void (){} // error

(强调地雷)

票数 10
EN

Stack Overflow用户

发布于 2022-10-28 10:10:01

如果允许的话,我如何分割arg1、args2和args3?

您不能。您可以使用std::tuple将模板包收集到一个参数中。

代码语言:javascript
运行
复制
template <typename... Args1, typename... Args2, typename... Args3>
void foo(std::tuple<Args1...> args1, std::tuple<Args2...> args2, std::tuple<Args3...> args3) {
    auto out = []<std::size_t... Is>(std::string name, auto tup, std::index_sequence<Is...>)
    {
        std::cout << name << " ";
        ((std::cout << get<Is>(tup) << " "), ...);
        std::cout << std::endl;
    };
    
    out("args1", args1, std::index_sequence_for<Args1...>{});
    out("args2", args2, std::index_sequence_for<Args2...>{});
    out("args3", args3, std::index_sequence_for<Args3...>{});
}

看它的实况

票数 1
EN

Stack Overflow用户

发布于 2022-10-29 15:26:00

我在“拥抱现代C++安全”一书中写了一章,并在https://www.youtube.com/watch?v=va9I2qivBOA的演讲中讨论了这一点和相关问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74233537

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档