Home > Software design >  Handling variadic function arguments of type 'std::size_t'
Handling variadic function arguments of type 'std::size_t'

Time:10-25

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!

CodePudding user response:

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.

CodePudding user response:

With C 20, you can create your SumIndices easily with the Concept library:

#include <concepts>
auto SumIndices(std::same_as<std::size_t> auto ... indices);

However, do note that this have a strict rule on only data of std::size_t or equivalent types can be passed to the function.

Instead, you might consider to use std::integral or std::unsigned_integral, which would allow other integral types to be used:

auto SumIndices(std::integral auto ... indices);
  • Related