Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic templates

Tags:

I have seen a lot of links introducing the variadic templates. But I have never seen any compilable example that demonstrates this approach.

Could someone provide me with some links in which such compilable examples can be found?

like image 535
sami Avatar asked Sep 03 '10 09:09

sami


People also ask

What is a variadic template C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.

What is variadic generic?

Variadic generics are necessary for an Array that is generic in an arbitrary number of axes to be cleanly defined as a single class.

What is a parameter pack?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.

What is Pack expansion?

Pack expansion (C++11) A pack expansion is an expression that contains one or more parameter packs followed by an ellipsis to indicate that the parameter packs are expanded. Consider the following example: template<class...T> void func(T...a){}; template<class...U> void func1(U...b){ func(b...


2 Answers

One of the simplest possible examples is the following implementation of max which isn't even templated on types.

int maximum(int n) {     return n; }  template<typename... Args> int maximum(int n, Args... args) {     return max(n, maximum(args...)); } 

Only slightly more complex is the canonical printf implementation:

void printf(const char *s) {   while (*s)   {     if (*s == '%' && *(++s) != '%')       throw "invalid format string: missing arguments";     std::cout << *s++;   } }  template<typename T, typename... Args> void printf(const char* s, T value, Args... args) {   while (*s)   {     if (*s == '%' && *(++s) != '%')     {       std::cout << value;       printf(s, args...); // call even when *s == 0 to detect extra arguments       return;     }     std::cout << *s++;   }   throw "extra arguments provided to printf"; } 
like image 142
Motti Avatar answered Sep 21 '22 21:09

Motti


Variadic templates are a C++0x feature that primarily targets authors of generic libraries. I would not expect to see them in "user code". For example, in the C++0x standard library they are used in a lot of places: std::function, std::async, std::reference_wrapper, std::tuple, std::packaged_task, ...

To give you an example I'll show you how a reference_wrapper might be implemented with respect to variadic templates:

template<class T> class reference_wrapper {     T *ptr; public:     explicit reference_wrapper(T& thing) : ptr(&thing) {}     explicit reference_wrapper(T&&     ) = delete;      operator T&() const {return *ptr;}      template<class... Args>     decltype( declval<T&>()(declval<Args>()...) )     operator()(Args&&... args) const     {         return (*ptr)(forward<Args>(args)...);     } }; 

This is not perfectly conforming to the standard draft but it is supposed to be compilable with little modification. It demonstrates multiple C++0x features:

  • deleted functions (disabling the constructor for rvalues)
  • rvalue references (detecting rvalue arguments to the constructor, perfect forwarding)
  • type deduction via decltype
  • standard library function template declval to create objects for the purpose of building an expression for decltype (GCC does not yet offer this function template. You have to write it yourself)
  • variadic templates (accepting an arbitrary number of parameters)

The purpose of the variadic member template is to forward arguments to the object referred to by ptr. This should work in case T is a function pointer type or a class type with overloaded function call operator.

cheers! s

like image 32
sellibitze Avatar answered Sep 21 '22 21:09

sellibitze