Power Programming Languages

Power Programming Languages

IBM Power, including the AIX, IBM i, and Linux operating systems, support a wide range of programming languages, catering to both traditional enterprise applications and modern development needs.


#Power

 View Only

C++ Templates What is a variadic template function?

By Archive User posted Mon August 27, 2012 08:37 AM

  

Originally posted by: camorton


The Variadic Template Function

The latest language standard has further complicated C++ by adding variadic templates. One problem I had in my attempt to understand this new feature was the lack of simple examples showing how it worked. Here's my attempt to show some of the basics of a variadic template function.
template <class ...A> int func(A... arg)
{
   return sizeof...(arg);
}

int main(void)
{
   return func(1,2,3,4,5,6);
}


First the basic vocabulary: A template parameter can now be a template parameter pack <class...A>. A template parameter pack represents any number of template parameters. In this example the template definition now has defined func with any number of template parameters.
The function argument (A... arg) is known as a function parameter pack and it represents one argument for every member of the indicated template parameter pack.
In the example, I call the function with 6 arguments. Template argument deduction then deduces parameter pack <class...A> to be <int,int,int,int,int,int> and the function parameter pack becomes (int,int,int,int,int,int) corresponding to the 6 integers passed in the call.
The variadic sizeof... simply returns the number of elements in the parameter pack (function or template). In this case we return 6.
 
Any parameter pack can be empty. Consider this similar example:
template <class ...A> int func(A... arg)
{
   return sizeof...(arg);
}

int main(void)
{
   return func();
}


In this case the template parameter pack is deduced to be empty which leaves the function parameter pack empty and we can call the function with no arguments and get 0 for our size.
 
The elements of the parameter pack do not need to be the same type:
template <class ...A> int func(A... arg)
{
   return sizeof...(arg);
}

struct s1{}; struct s2{}; struct s3{};

int main(void)
{
   s1 t1; s2 t2; s3 t3;
   return func(t1,t2,t3);
}


In this case the parmaeter pack is deduced to <s1,s2,s3>.
 
In the previous examples, the parameter pack for for a type parameter, but you can also have a non-type parameter pack as in this example:
template <bool ...A> int func()
{
   return sizeof...(A);
}

int main(void)
{
   return func<true,false,true,false>();
}


These simple examples show the syntax. Counting the number of elements is cute, but the pack is not much use if the elements cannot be accessed.
To access the elements of the parameter pack in a function template, overload the function:
#include <iostream>
using namespace std;

void func()
{
   cerr << "EMPTY" << endl;
}

template <class A, class ...B> void func(A argHead, B... argTail)
{
   cerr << "A: " << argHead << endl;
   func(argTail...);
}


int main(void)
{
   func(1,2,3,4,5,6);
   return 0;
}



In this example, there are 2 candidate functions matching the call. In this case one is a non-template. Since the non-template candidate has no function parameters, this will only match a function call func(), all other calls need to match the template candidate.

In order to match a template candidate function the compiler has to deduce the template parameters from the function call arguments, then it instantiates the template function.
This template function has its first argument based on an ordinary template parameter <class A> and its second argument based on a parameter pack. The second argument is a function parameter pack. The first template parameter will be deduced to the type of the first argument. The type of each member of the parameter pack will be based on all the remaining arguments.

The whole thing begins with the function call in main func(1,2,3,4,5,6);
Template parameter <class A> is deduced to <int> and template parameter pack <class...B> is deduced to <int,int,int,int,int>
The compiler instantiates the function template
#C/C++-compilers-for-AIX
#C/C++andFortran
2 comments
1 view

Permalink

Comments

Mon August 27, 2012 05:05 PM

Originally posted by: Xavier Nodet


Variadic templates have very interesting uses: in particular, they allow to write perfectly type-safe printf-like functions, or classes like std::tuple. You can find more information about their uses in the proposal that was brought forward the C++ standardization committee (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf) or in Andrei Alexandrescu's talk at Going Native 2012 (http://youtu.be/_zgq6_zFNGY)

Mon August 27, 2012 05:01 PM

Originally posted by: rollie42


A simple applied example I wrote a couple months ago when learning this shows its usefulness: template