Please explain to me why the following piece of code complies and works perfectly. I am very confused.
#include<iostream>
template<class A = int, class B=double>
class Base
{};
template<class B>
class Base <int, B>
{
public:
Base()
{
std::cout<<"it works!!!!!\n";
}
};
int main()
{
Base<> base; // it prints "it works!!!!!"
return 0;
}
Shouldn't it fall into the generalized form of the template class Base?
You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
The default argument applies to the specialization -- and, in fact, a specialization must accept (so to speak) the base template's default argument(s). Attempting to specify a default in the specialization:
template<class A = int, class B=double>
class Base
{};
template<class B=char>
// ...
...is an error.
Likewise, if we change the specialization so that its specialization is for a type other than the default provided by the base template:
template<class A = int, class B=double>
class Base
{};
template<class B>
class Base <char, B>
...then the base template will be chosen.
So, what's happening is this: first the types for the template arguments are chosen. In this case (no type specified at instantiation), both types are based on the default template arguments specified in the base template.
Then (as a basically separate step) it carries out an analog of overload resolution on all templates that fit those argument types. As usual for overload resolution, a type that's specified explicitly is preferred over one that's specified implicitly, so your specialization (which specified int
explicitly) is preferred over the base template (which specified int
implicitly).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With