Search code examples
c++c++17variadic-templatesc++20variadic-functions

Handling variadic function arguments of type 'std::size_t'


I am trying to get the hang of variadic function/template parameters. However, in the two functions below, I am very confused as to why SumIndices does not compile (I get the compiler error "expansion pattern ‘std::size_t’ {aka ‘long unsigned int’} contains no parameter packs") while SumValues does.

template <typename ...t_data_type>
constexpr auto SumValues(t_data_type ..._values) { 
  return (_values + ...); 
}

constexpr auto SumIndices(std::size_t ..._indices) { 
  return (_indices + ...); 
}

I would much appreciate it if anyone can clarify this confusion for me!


Solution

  • In first case you have parameter pack. In second case, you have variadic function from C.

    Variadic templates allow you to type-safely pass different types into your function. Example of print with this:

    // Create this function to terminate argument depended lookup
    void PrintValues(std::ostream&){}
    template<typename TFirstArg, typename ...TArgs>
    void PrintValues(std::ostream& output, const TFirstArg& arg, const TArgs... other_args){
       // Recursive call to another function which has N-1 args
       // If other_args are empty, it would call `void PrintValues(std::ostream&)`
       // If they are non empty, it would call another instantiation of this template
       PrintValues(output << arg, other_args...);
    }
    

    And this can be called this way:

    PrintValues(std::cout, 5LL, 7.59, "Hello world", std::string{"bingo"});
    

    With varargs you can do this:

    void PrintFewNumbers(size_t number_of_args, ...)
    {
        va_list args;
        va_start(args, number_of_args);
        for (size_t idx_of_arg, idx_of_arg < number_of_args; ++idx_of_arg){
            size_t current_arg = va_arg(args, size_t);
            std::cout << current_arg;
        }
        va_end(args);
    }
    

    And you can call it using this:

    PrintFewNumbers(0);
    PrintFewNumbers(5, 1,2,3,4,5);
    

    You should prefer variadic templates to variadic args because they are type safe. However, they are not always usable.