Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

variadic function template without formal parameters

This is what I'm trying to do:

// base case
void f() {}

template <typename T, typename... Ts>
void f() {
    // do something with T
    f<Ts...>();
}

int main() {
    f<int, float, char>();
    return 0;
}

It doesn't compile:

prog.cpp: In instantiation of ‘void f() [with T = char; Ts = {}]’:
prog.cpp:6:5:   recursively required from ‘void f() [with T = float; Ts = {char}]’
prog.cpp:6:5:   required from ‘void f() [with T = int; Ts = {float, char}]’
prog.cpp:10:25:   required from here
prog.cpp:6:5: error: no matching function for call to ‘f()’
prog.cpp:6:5: note: candidate is:
prog.cpp:4:6: note: template<class T, class ... Ts> void f()
prog.cpp:4:6: note:   template argument deduction/substitution failed:
prog.cpp:6:5: note:   couldn't deduce template parameter ‘T’

This thread shows a way to fix this, but the base case has to be a template. I don't really like it, because as far as I understand I will have to duplicate code that works with T. Is there a way to avoid that?

So far I came up with two solutions (http://ideone.com/nPqU0l):

template <typename...> struct types_helper {};

// base case
void f(types_helper<>) {}

template <typename T, typename... Ts>
void f(types_helper<T, Ts...>) {
    // do something with T
    f(types_helper<Ts...>());
}

int main() {
    f(types_helper<int, float, char>());
    return 0;
}

http://ideone.com/yyg6y9:

#include <type_traits>

struct end_of_list;

template <typename T>
void f() {
    static_assert(std::is_same<T, end_of_list>::value, "error");
}

template <typename T1, typename T2, typename... Ts>
void f() {
    // do something with T
    f<T2, Ts...>();
}

int main() {
    f<int, float, char, end_of_list>();
    return 0;
}

I wonder if there is a better way to do this.

like image 463
catscradle Avatar asked May 26 '13 11:05

catscradle


People also ask

What are variadic function templates in C++?

Variadic function templates in C++. Variadic templates are template that take a variable number of arguments. Variadic function templates are functions which can take multiple number of arguments.

What are variadic arguments in C++?

Douglas Gregor and Jaakko Järvi came up with this feature for C++. Variadic arguments are very similar to arrays in C++. We can easily iterate through the arguments, find the size (length) of the template, can access the values by an index, and can slice the templates too.

What is a variadic function?

Variadic Functions. A function with variable number of… | by Chuan Zhang | The Startup | Medium A function with variable number of arguments is called a variadic function, and also known as variable argument function [1]. Due to its flexibility in size of the list of input arguments, it is very useful especially in system programming.

How to know how many arguments are actually passed in variadic templates?

When using variadic templates you may end up in a situation, where you would like to know how many arguments are actually passed. Let’s say that you want to store them in a table. How big should it be? sizeof... () will tell you: template <typename... Args> void func (Args... args) { int argsTable [sizeof... (args)] = {args...};


1 Answers

Since c++20 you can use constraints to functions, instead of SFINAE.

template <typename... Ts>
requires (sizeof...(Ts) == 0)
void f(){}

template <typename T, typename... Ts>
void f() {
    // do something with T
    f<Ts...>();
}
like image 170
SebastianH Avatar answered Oct 20 '22 00:10

SebastianH