Reputation: 96845
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
?
Upvotes: 7
Views: 510
Reputation: 45725
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.
Upvotes: 5
Reputation: 18761
The reason you can leave the template arguments out is because c++11 has template argument deduction template<args ...>
is a variadic template which is basically a pack of possibly different typenames. This website explains the omission of template arguments. From reading further into the deduction of non type template arguments, which the compiler can deduce I believe that the compiler is realizing that they are never used (with clang at least) and making it's deduction based on that, read the deducing non type template arguments portion of the website
Upvotes: 0