for_each_argument -- Sean Parent

Sean Parent just published via Twitter this amazing short piece of code.

for_each_argument

by Sean Parent

The code is:

template <class F, class... Args>
void for_each_argument(F f, Args&&... args) {
    [](...){}((f(std::forward<Args>(args)), 0)...);
}

Add a Comment

Comments are closed.

Comments (3)

1 0

seth said on Jan 23, 2015 10:09 PM:

Of course the function calls are not guaranteed to be called in any particular order with this implementation.
for_each_argument([](auto a) { cout << a; }, 1,2,3,4,5)
could print "52431". The order can be guaranteed by expanding the parameter pack expression in a different context, such as that of an array initializer:
int _[] = {(f(std::forward<Args>(args)),0)...};


Also, I see that Sean Parent posted a similar fix:
(void)(int[]){(f(forward<Args>(args)), 0)...};


However his update uses C99 syntax (compound literals). This can be converted to C++:
using arrT = int[];
static_cast<void>(arrT{(f(std::forward<Args>(args)), 0)...});
0 0

Luca Risolia said on Jan 24, 2015 04:33 PM:

Note that the original version of for_each_argument can be called when the number of elements in the parameter pack is 0, while this is not possible with the other versions, because it's not possible to initialize zero-length arrays. This can be easily fixed by adding one element in the initializer list. Another solution is to use std::array, which can be zero-length as special case:

std::array<int, sizeof...(Args)>{(f(std::forward<Args>(args)), 0)...};


Of course, whether calling for_each_argument with no arguments in the parameter pack is useful or not is another issue.

0 0

Marco Arena said on Jun 11, 2015 01:56 AM:

Thanks to fold expressions, in C++17 we'll write:

template<typename Fun, typename...T>
Fun for_each(Fun fun, T&&... args)
{
(fun (forward<T>(args)), ...);
return fun;
}