GOPHERSPACE.DE - P H O X Y
gophering on raymii.org
This is a text-only version of the following page on https://raymii.org:
---
Title       :  C++ variadic template recursive example
Author      :  Remy van Elst
Date        :  08-06-2019
URL         :  https://raymii.org/s/snippets/Cpp_variadic_template_recursive_example.html
Format      :  Markdown/HTML
---



In this article I'll show you how to use a variadic template in C++. Variadic
templates allow you to have a template with a variable number of  arguments,
also called a parameter pack. Unpacking that pack is more difficult than it
should be, so we use a recursive template to iterate over all the  parameters
one by one. I've also included an example in Python to compare to.

 Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics.
 Please, if you found this content useful, consider a small donation using any of the options below:


 ://leafnode.nl">I'm developing an open source monitoring app called  Leaf Node Monitoring, for windows, linux & android. Go che
ck it out!

 Consider sponsoring me on Github. It means the world to
 me if you show your appreciation and you'll help pay the server costs.

 ode=7435ae6b8212">You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $100 credit for 60
 days. 

 




### Variadic templates

Variadic templates allow you to have a template with a variable number of 
arguments, also called a parameter pack. They were introduced in C++ 11, 
before that you had to use `va_` macros with the ellipsis `(...)` operator, 
which is not type-safe and quite complex.

My use case was to have a template that allows an arbitrary number of arguments,
of a few different types which will all be processed one by one sequentially. If
you're looking to get  all of the template pack and to something with it at
once, this guide isn't for you. That requires either an `initializer list` or a
`tuple`.

[This][1] is a great article on variadic templates with more examples. 
[Wikipedia][2] also has a page with some examples. [This][3] is also a good
introduction.

Quoting Kevin from the last linked article:

> When it comes to handling variadic functions, you can't think in the standard
`iterative` C++ style. You need to write such functions recursively, with a
`base` case, and a `recursive` case that reduces, eventually, into a `base`
case. This implies a separate function for each case.

It took me a while to find out how to use the argument pack. At the end of this
article is a comparison to Python, which is what I was used to before going into
C++. There, you can use `Foo(*args)` or  `Foo(**kwargs)` and a `for` loop. In
C++ that for loop isn't easily possible. 

Quoting [davmac][5] from lobste.rs who has an explanation on why this is not as 
easy as I would hope:

> C++ for loops were traditionally a run-time loop and so they don't apply to
parameter packs which are a compile-time construct only. While a for loop can
now be evaluated at compile time (in a constexpr function) their syntax and
semantics are unchanged in that case, i.e. they still apply to constructs that
are (or at least which can also be) run-time. Allow for loops to iterate through
parameter packs would require new syntax and semantics in a language that many
feel is already getting too complex. That said I suspect you could do this with
something more like a regular loop with C++2x features (or possibly even C++17,
I haven't been keeping up to well) e.g. with template lambdas.

Unpacking the pack to a `std::tuple` is possible, but tricky to use afterwards.
By using the ellipsis `(...)` operator in the correct place (left or right of a
parameter name) we can control what happens. 

Placing the ellipsis to the left of the parameter name declares an parameter
pack. You use this in the template declaration, like so:

    template 
    void Foo(First first, Args... args) { }

Placing the ellipsis to the right of the parameter will cause the whole
expression that precedes the ellipsis to be repeated for every subsequent
argument unpacked from the argument pack. In our example, it is used in the
variadic function to call the base function:

     Foo(args...);

The below `Foo()` example is recursive. The template function with `First` and
`Args...` calls the template with `Arg`, which performs the actual action we
want. Both functions have the same name, thus being overloaded. There also is a 
function (not template) which takes no arguments, but that is up to you if you
need that. The functions could be named different (`Base(Arg)` and 
`Other(First, Args...)` e.g.). 

The `First` argument is required to get the 'One or more' behaviour. If you
would omit it, `Foo(Args...)` would accept zero or more parameters. 


### void Foo() example

Tested with `CLion` in C++ 11 mode.

    // non template function to call with zero arguments
    void Foo() {
        std::cout << " ";
    }

    // base template with 1 argument (which will be called from the variadic one).
    template 
    void Foo(Arg arg) {
        //std::cout << __PRETTY_FUNCTION__ << "\n";
       std::cout << arg << " ";
    }

    // variadic template with one or more arguments.
    // ellipsis (...) operator to the left of the parameter name declares a parameter pack,
    // allowing you to declare zero or more parameters (of different types).
    template 
    void Foo(First first, Args... args) {
        //std::cout << __PRETTY_FUNCTION__ << "\n";
        Foo(first);
        Foo(args...);
        //  ellipsis (...) operator to the right of the parameter name will cause
        //  the whole expression that precedes the ellipsis to be repeated for every
        //  subsequent argument unpacked from the argument pack, with the expressions
        //  separated by commas.
    }

    int main() {
        std::string one = "One";
        const char* two = "Two";
        float three = 3.3333333333;

        Foo(); // non template
        std::cout << std::endl;

        Foo(one); // base template
        std::cout << std::endl;

        Foo(one, two); // variadic argument template
        std::cout << std::endl;

        Foo(one, two, three);  // variadic argument template
        std::cout << std::endl;

        Foo(1, 2, three, 4, 5.7, 6/2, "lalala");  // variadic argument template
        return 0
    }

Example output:

    One 
    One Two 
    One Two 3.33333 
    1 2 3.33333 4 5.7 3 lalala 


### PRETTY_FUNCTION

    __PRETTY_FUNCTION__

contains the name of the current function as a string, and
for C++ functions (classes, namespaces, templates and overload) it contains the
`pretty` name of the function including the signature of the function. It is a
`gcc` [extension][4] that is mostly the same as    

    __FUNCTION__

or 

    __func__


By placing 

    std::cout << __PRETTY_FUNCTION__ << "\n"

at the top of the
function, you can get an overview of what is called and when. Consider the
following example:

    template 
    void Foo(Arg arg) {
        std::cout << __PRETTY_FUNCTION__ << "\n";
    }

    template 
    void Foo(First first, Args... args) {
        std::cout << __PRETTY_FUNCTION__ << "\n";
        Foo(first);
        Foo(args...);
    }

    int main() {
        std::string one = "one";
        const char* two = "two";
        Foo(one); // base template
        std::cout << std::endl;
        Foo(one, two); // variadic argument template
        std::cout << std::endl;
    }

Will output:

    void Foo(Arg) [with Arg = std::__cxx11::basic_string]

    void Foo(First, Args ...) [with First = std::__cxx11::basic_string; Args = {const char*}]
    void Foo(Arg) [with Arg = std::__cxx11::basic_string]
    void Foo(Arg) [with Arg = const char*]

The first line is the base template. After the newline, the variadic template 
is called and that calls the base template twice.

### Python

In Python preceding a method parameter with an asterisk (`*args`) defines it as
a variable non-keyword list of arguments. Preceding with two asterisks
(`**kwargs`) defines the parameter as a keyworded list of arguments. The
parameters can be named anything as long as the asterisks are there, but
convention says to use `*args` and `**kwargs`.



A small example of the above `Foo()` method in Python. Newline printing is
omited by appending the comma (`,`) to the `print()` function.

    #!/usr/bin/python

    def Foo(first, *argv):
        print(first),
        print(" "),
        for arg in argv:
            print(arg),
            print(" "),
        print("")
            

    bla = "Hello"
    Foo('one')
    Foo('one', 'two')
    Foo('Remy', 2, 2.4, bla)

Output:

    $ python test.py
    one
    one   two
    Remy   2   2.4   Hello

An example using keyworded args (`**kwargs`):

    #!/usr/bin/python
    def Foo2(**kwargs):
        if kwargs:
            for key, value in kwargs.iteritems():
                print("%s: %s, ") % (key,value),
        print("")

    bla = "Hello"
    Foo2(first='one')
    Foo2(first='one', second='two')
    Foo2(first='one', second='two', three=3, var=bla)

Output:

    first: one,
    second: two,  first: one,
    var: Hello,  second: two,  three: 3,  first: one,


[1]: http://web.archive.org/web/20190608070158/https://eli.thegreenplace.net/2014/variadic-templates-in-c/
[2]: https://en.wikipedia.org/wiki/Variadic_template
[3]: http://web.archive.org/web/20190608183836/https://kevinushey.github.io/blog/2016/01/27/introduction-to-c++-variadic-templa
tes/
[4]: https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
[5]: http://web.archive.org/web/20190613053209/https://lobste.rs/s/qswclv/variadic_templates_vs_kwargs_c_makes_it

---

License:
All the text on this website is free as in freedom unless stated otherwise. 
This means you can use it in any way you want, you can copy it, change it 
the way you like and republish it, as long as you release the (modified) 
content under the same license to give others the same freedoms you've got 
and place my name and a link to this site with the article as source.

This site uses Google Analytics for statistics and Google Adwords for 
advertisements. You are tracked and Google knows everything about you. 
Use an adblocker like ublock-origin if you don't want it.

All the code on this website is licensed under the GNU GPL v3 license 
unless already licensed under a license which does not allows this form 
of licensing or if another license is stated on that page / in that software:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .

Just to be clear, the information on this website is for meant for educational 
purposes and you use it at your own risk. I do not take responsibility if you 
screw something up. Use common sense, do not 'rm -rf /' as root for example. 
If you have any questions then do not hesitate to contact me.

See https://raymii.org/s/static/About.html for details.