Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it mean to unpack a parameter pack into another template declaration?

Tags:

c++

c++11

I don't understand how the following feature should be used. When I call A::f I can omit the template parameters, but I don't understand why.

template <typename... Args>
struct A
{
    template <Args...>
    void f() {}
};

int main()
{
    A<int, bool> a;
    a.f();
}

To be specific, what does the template <Args...> mean and why can I leave the template parameters out of the function call to f?

like image 513
David G Avatar asked May 29 '13 19:05

David G


1 Answers

template<typename ...Args> is a variadic template. It means, that you can specify any number of template type parameters, but I think you already know this.

Whenever Args... appears in the template code, it will be unpacked ("expanded") to the types of the instantiation. In your example, this is int, bool. So your class becomes, when fully expanded, this definition:

struct A<int, bool>
{
    template <int, bool>
    void f() {}
};

This means, A<int,bool>::f() is again templated (the arguments are unpacked into another template declaration, as you called it), but this time with non-type template parameters with the types int and bool (they're anonymous), so you could instantiate f() for example like this:

a.f<1, true>();

Unfortunately, g++ seems to have a bug and won't accept this piece of code, while it accepts your code.

clang accepts both codes. I expect that in your code, clang doesn't care if the int and bool template parameters are omitted, but it doesn't complain either when they are specified (in contrast to g++).

Usage example:

If you want to use the specified values, they can't be anonymous (obviously). You can, for example, provide a format string in f() which is used to "printf" the template values, like this:

template <Args ...values>
void f(const char *fmt) {
    std::printf(fmt, values...);
}

Then, the following code

A<int> a;
a.f<42>("The answer is %d!\n");

will print:

The answer is 42!

But, using the syntax from above (Args... being expanded to anonymous non-type template parameters), the template parameters are essentially useless.

Without specifying values, it still compiles (which surprised me!) and prints an uninitialized int value.

like image 160
leemes Avatar answered Sep 28 '22 17:09

leemes