Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expand parameter pack with index using a fold expression

I've got a template function taking a parameter pack. I want to expand it into calls to a second function while also supplying the index of the item in the pack. I probably can work out how to do it with recursion but I would like to try do it with a fold expression.

This is the function I want the parameter pack to expand into

template<typename T>
void addToRecord(Record& rec, int idx, T&& val)
{
    // Do some stuff.
}

And this is the function that takes the parameter pack

template<typename... ARGS>
void addRecord(ARGS&& ...values)
{
    Record rec;
    // addToRecord(rec, ??????)  How do expand 'values' here addToRecord with index of each item?
}

Is this possible? I realize this isn't critical but I'm also trying to get better with using fold expressions.

like image 567
Joe Avatar asked Dec 31 '22 13:12

Joe


2 Answers

In addition to another answer let me mention a simpler approach that doesn't need a helper function:

template<typename... Args>
void addRecord(Args&&... values) {
    Record rec;

    int i = 0;
    (addToRecord(rec, i++, std::forward<Args>(values)), ...);
}

The comma operator , guarantees that all addToRecord()s will be called in order:

In a comma expression E1, E2, the expression E1 is evaluated, its result is discarded, and its side effects are completed before evaluation of the expression E2 begins.

like image 139
Evg Avatar answered Jan 28 '23 09:01

Evg


You can write a helper function that takes a compile time integer sequence, along with the values

template<typename... Args, std::size_t... Is>
void addRecord_impl(Record& rec, std::index_sequence<Is...>, Args && ...values)
{
    (addToRecord(rec, Is, std::forward<Args>(values)), ...);  // Is and values will be expanded in lock step
}

and then call this helper like this

template<typename... Args>
void addRecord(Args && ...values)
{
    Record rec;
    addRecord_impl(rec, 
                   std::index_sequence_for<Args...>{}, 
                   std::forward<Args>(values)...);
}

Here's a demo

like image 25
cigien Avatar answered Jan 28 '23 10:01

cigien