2022-11-13

Iterating over Variadic arguments

I'm sure this question has been asked before, but I can't seem to find something as simple as what I'm trying to do. Essentially, I just want to make sure the code triggers each parameter, calling any functions that may be sent as inputs. My biggest worry here is that optimizations may remove some of the calls, changing the result.

I was using the following syntax. It seemed to trigger the function calls the way I want, but it has the strange result of triggering the arguments in reverse order - the last argument is called first, and the first argument is called last:

template <typename... PARMS> uint PARMS_COUNT(PARMS&& ... parms) { return static_cast<uint>( sizeof...(parms) ); }

This was my first guess as to how to do the same thing (edit: this does not change the order - it still happens in reverse, because the order is being determined by the function parameter evaluation, rather than what order the function uses them in):

template <typename FIRST>
constexpr uint PARMS_EXPAND(FIRST &&first)
{
    return static_cast<uint>( sizeof(first) > 0 ? 1 : 0 );
}
template <typename FIRST,typename... PARMS>
constexpr uint PARMS_EXPAND(FIRST &&first,PARMS&& ... parms)
{
    return static_cast<uint>( sizeof(first) > 0 ? 1 : 0 ) + PARMS_EXPAND( std::forward<PARMS>(parms)... );
}

I tested this in a few places, but then realized that regardless of how much testing I do, I'll never know if this is a safe way to do it. Is there a standard or well known method to pull this logic off? Or even better, some built in system to iterate over the arguments and "access them" in the correct order?

To better explain why I would want to trigger code like this, consider a function that can add new objects to a parent:

void AddObject(/*SINGLE UNKNOWN INPUT*/)
{
    ...
}
template <typename... PARMS> AddObjects(PARMS&& ... parms)
{
    PARAMS_EXPAND( AddObject(parms)... );
}


No comments:

Post a Comment