While mfontanini's solution works and is good because it performs the calculation of the incrementing column index at compile time, I think it's worthwhile pointing out that there is also a direct answer to question of how to increment an int in a variadic pack expansion. (Unfortunately it does not seem to work on GCC due to a bug, see the caveat at the end.)
The answer is based on the fact that while the evaluations of arguments in a function call are unsequenced, the evaluations of arguments in a list initialization are not:
(§8.5.4/4) Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.
[ Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. — end note ]
Therefore, if you transform your function call into something based on a brace-init-list, you'll get the desired effect:
rowCallback(std::tuple<ColumnTypes...> { getColumn<ColumnTypes>(column++)... });
This initializes a std::tuple
using list-initialization (notice the braces { ... }
), hence the column++
side effect will be performed in left-to-right order.
If written as above, this means you need to change rowCallback()
to make it accept a std::tuple
instead of a list of arguments. If you don't like this, you can create a separate template function call_on_tuple(fun,tup)
, which calls any function fun
on the arguments that result from expanding tuple tup
. I once described how to do this here, or if you like, you could use rlxutil::call_on_tuple
from my GitHub repository.
Your execute
function then looks like this:
template <typename... ColumnTypes>
void execute(function<void(ColumnTypes...)> rowCallback)
{
using std::tuple;
using rlxutil::call_on_tuple;
int column = 0;
call_on_tuple(rowCallback,
tuple<ColumnTypes...> { getColumn<ColumnTypes>(column++)... });
}
Caveat: This is does not work as expected with GCC. I believe this is because of the bug reported here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253.