I'm really happy to have discovered for_each_arg(...)
, which makes dealing with argument packs much easier.
template<class F, class...Ts> F for_each_arg(F f, Ts&&...a) { return (void)std::initializer_list<int>{(ref(f)((Ts&&)a),0)...}, f; }
I'm, however, confused on its correct usage. There are many arguments that need to be perfectly forwarded, but am I performing any unnecessary forwarding?
Reading the code becomes harder with excessive fowarding.
struct UselessContainer
{
// Expects a perfectly-forwarded item to emplace
template<typename T> void add(T&&) { }
};
// Creates an `UselessContainer` already filled with `mArgs...`
auto makeUselessContainer(TArgs&&... mArgs)
{
using namespace std;
UselessContainer result;
for_each_arg
(
[&result, &mArgs...] // Am I capturing the `mArgs...` pack correctly here?
(auto&& mX) // Am I passing the arguments to the lambda correctly here?
{
// Is this `forward` necessary?
result.add(forward<decltype(mX)>(mX));
// Could it be replaced with
// `result.add(forward(mX));`
// ?
},
forward<TArgs>(mArgs)... // I assume this `forward` is necessary.
);
return result;
}
All my questions/doubts are expressed in the comments in the above code example.