【问题标题】:Passing each argument of a variadic function template into a function that returns void将可变参数函数模板的每个参数传递给返回 void 的函数
【发布时间】:2015-07-31 19:02:32
【问题描述】:

根据here找到的配方,我写了以下内容:

void printInt(int a) {std::cout << a << std::endl;}

template <typename... Args>
void f(const Args &... args) {
    auto temp = {(printInt(args), void(), 0)...};
    auto a = temp; temp = a;
}

两个问题:

  1. 这个语法是什么意思:{(printInt(args), void(), 0)...}

  2. 我添加了auto a = temp; temp = a; 行,以免收到有关未使用变量temp 的警告。有没有更好的办法?


经过回复和cmets的解释,剩下的唯一问题是:为什么C++不允许这样做:

template <typename... Args>
void f(const Args &... args) {
    printInt(args)...;
} 

在引用的帖子中提出了这个问题,但没有得到任何答案。

【问题讨论】:

    标签: c++ templates c++11 variadic-templates


    【解决方案1】:
    1. 此语法意味着,temp 将被填充零,由于逗号运算符规则(所有表达式都将被计算,但只会使用最后一个,因此,函数 printInt 将为每个参数调用并且 0 将被放入每个参数的初始化列表中)。

    N4296 5.19/1

    一对用逗号分隔的表达式从左到右计算; 左边的表达式是一个弃值表达式(第 5 条)。 87 与左相关的每个值计算和副作用 表达式在每个值计算和副作用之前排序 与正确的表达相关联。结果的类型和值 是右操作数的类型和值;结果是一样的 值类别作为它的右操作数,如果它的右操作数是一个位域 操作数是一个左值和一个位域。如果正确的值 操作数是临时的(12.2),结果是临时的。

    {(printInt(args), void(), 0)...};
    

    () 用于包扩展,因此,... 将应用于完整表达式,void() 用于保护构造免受类重载运算符,(感谢 Quentin),您也可以使用以下

    {((void)printInt(args), 0)...};
    

    还有,用起来会更好

    {0, ((void)printInt(args), 0)...};
    

    对于initializer_list 中的至少一个元素(因此您可以在不带参数的情况下调用f)。

    1. 您可以使用(void)temp; 标记未使用的变量,这里有更多信息:What does (void) 'variable name' do at the beginning of a C function?

    【讨论】:

    • 这个答案太简洁了。我不明白 1 到底发生了什么:圆括号和void() 的作用是什么?另外,对于2,为什么编译器不抱怨该语句对(void)temp;无效?
    • void() 是为了保护构造免受类重载operator ,
    • @ForEveR 要迂腐,可能会有 ;) printInt 被称为不合格,你不能保证 Args 都是 ints,所以你可能会通过 ADL 捡到一些奇怪的东西. :P(不过,该问题的解决方法可能是通过合格的调用来抑制 ADL。)
    • @MeirGoldenberg 当然!类有可能重载operator ,,即逗号运算符。假设printInt(arg)返回Foo,那么如果存在重载的Bar operator , (Foo, int),它将被(printInt(args), 0)调用。如果Bar 对于每个可能的Foo 并不总是相同的类型,那么您最终会尝试将不同类型的对象填充到相同的std::initializer_list 中,这是一个错误。
    • @MeirGoldenberg 现在,解决方案:void() 不完全是一个空表达式转换(没有空表达式),但结果是相同的:您获得了一个 void 类型的表达式。而且不可能制定一个重载的operator , (Foo, void)operator , (void, int)。通过插入void 表达式,您可以确定内置的逗号运算符是被使用的。
    猜你喜欢
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 2011-03-16
    • 1970-01-01
    • 2015-09-07
    • 1970-01-01
    相关资源
    最近更新 更多