Default template argument and partial specialization
Asked Answered
P

4

65

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?

Paddlefish answered 9/9, 2013 at 14:27 Comment(3)
+1 for teaching me that default arguments go on to apply to specializations.Mcclanahan
+1 for pretty-much the same reason @Mcclanahan said. didn't see that coming whatsoever.Meteorite
I agree. An excellent question and (particularly), a superb job of asking it, complete with SSCCE and good description of both actual and expected behavior. Well done!Wretched
W
46

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).

Wretched answered 9/9, 2013 at 15:7 Comment(1)
Jerry, for your information, I posted a question which relates to a statement you make here: "if we change the specialization so that its specialization is for a type other than the default provided by the base template then the base template will be chosen": #52584333Retribution
B
0

When you write Base<> base; the compiler will try to find out if instantiation of Base<> class is possible or not if it is possible the code would work fine. In this case it is possible due to the default template argument of Base because the compiler knows if you if you write Base<> it needs to create a object of Base<int,double>. i.e: because of:

template<class A = int, class B=double>
class Base
{};

So the code works fine.

Blasting answered 9/9, 2013 at 14:37 Comment(5)
The question is why it shouldn't fali? @SakshamBlasting
does it answer the question??Tephra
As default argument is provided the code will work. I think that's the answerBlasting
This answer, as far as I can tell, is saying the text should not be printed.Mcclanahan
@Mcclanahan why is that? where my logic won't hold true?Blasting
G
0
template<class A = int, class B=double>
class Base
{};

Here the default values/initialization for A and B have been declared respectively as int and double.

 template<class B>
 class Base <int, B>

Here in class definitions, the first argument is something like a constant value(here int; why declare this way just making things complex? Better remove the first template argument) and the second template argument is B who default value is 'double'.

Base<> base;

When you create the object of the class. Although you do not specify the template arguments, the compiler takes default values of the arguments(A and B)which are 'int' and 'double' and the code executes without any errors or warnings.
See what happens when you create the object as:
Base<float,char> b; or Base<char,char> b;

Gandy answered 9/9, 2013 at 14:59 Comment(1)
I believe the question is: why is the partial specialization chosen rather than the primary template in this case. I don't see this addressed in your answer.Villareal
D
0

TL;DR:

template<class A = int, class B=double> class Base {}
  • This line defines the primary template. The primary template must be more general. In this case, it accepts ANY types of A and B, i.e., Base<> base;
  • Meanwhile, A = int and B = double are default values, meaning that instantiate Base<> base with no template arguments is actually Base<int, double> base.
  • Then the first parameter int happens to match Base <int, B>, the partial specialized template, thus the "it works" function is called.
Dusa answered 15/6, 2023 at 12:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.