简体   繁体   中英

Passing each argument of a variadic function template into a function that returns void

Based on the recipe found here , I wrote the following:

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;
}

Two questions:

  1. What does this syntax mean: {(printInt(args), void(), 0)...} ?

  2. I added the line auto a = temp; temp = a; auto a = temp; temp = a; in order to not get a warning about the unused variable temp . Is there a better way?


After the explanations in the reply and the comments, the only question that remains is: why doesn't C++ allow for this:

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

This question was asked in the cited post, but did not receive any answer.

  1. This syntax means, that temp will be std::initializer_list<int> filled with zeros, due comma operator rules (all expressions will be evaluated, but only last will be used, so, function printInt will be called for each argument and 0 will be putted to initializer list for each argument).

N4296 5.19/1

A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded- value expression (Clause 5). 87 Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field. If the value of the right operand is a temporary (12.2), the result is that temporary.

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

() is for pack expansion, so, ... will be applied to full expression, void() is here to shield the construct against classes overloading operator , (thanks Quentin), you can also use following

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

Also, it will be better to use

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

for at least one element in initializer_list (so you can call f without arguments).

  1. You can use (void)temp; to mark variable unused, here is more info: What does (void) 'variable name' do at the beginning of a C function?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM