Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic expander without a typedef

One trick often used to perform a variadic parameter expansion is using an un-sized array typedef in combination with the comma operator, like below:

#include <iostream>

template<typename... Ts>
void expander(Ts&&... ts)
{
    using expand = int[];
    (void)expand{0, (std::forward<Ts>(ts)(), 0)...};
}
void f()
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
    expander(f, f);
}

Live on Coliru

Can we do this without introducing a typedef? If I try directly

(void)int[]{0, (std::forward<Ts>(ts)(), 0)...};

gcc/clang spit out

error: expected primary-expression before 'int'

and if I try to parenthesize, the code compiles but I believe it is non-standard compliant:

warning: ISO C++ forbids compound-literals [-Wpedantic]

like image 995
vsoftco Avatar asked Feb 05 '16 21:02

vsoftco


1 Answers

In this expression

(void)int[]{0, (std::forward<Ts>(ts)(), 0)...};

you're trying to use a functional notation cast to create a temporary array. That won't work because the language only allows the functional notation to be used with either a simple-type-specifier or a typename-specifier.

From [expr.type.conv]/3

Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (8.5.4) with the specified braced-init-list, and its value is that temporary object as a prvalue.

And if you go lookup the definition of simple-type-specifier under [dcl.type.simple], it doesn't include anything with array brackets. In fact, it doesn't even include anything that's more than one word. This is why writing int(1) is valid, but signed int(1) isn't.

So, with C++11/14 you need a typedef or declare an array variable. But, with a C++1z compiler, you can make use of fold expressions and avoid both

template<typename... Ts>
void expander(Ts&&... ts)
{
    (void(std::forward<Ts>(ts)()), ...);
}

Live demo

like image 50
Praetorian Avatar answered Nov 02 '22 22:11

Praetorian