Частичная специализация параметра шаблона по умолчанию

Пожалуйста, объясните мне, почему следующий фрагмент кода работает идеально. Я очень смущен.

#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;
}

Разве он не должен упасть в обобщенную форму шаблонного класса Base?


person Andy    schedule 09.09.2013    source источник
comment
+1 за то, что научил меня тому, что аргументы по умолчанию продолжают применяться к специализациям.   -  person chris    schedule 09.09.2013
comment
+1 почти по той же причине, что и @chris. вообще не ожидал этого.   -  person WhozCraig    schedule 09.09.2013
comment
Я согласен. Отличный вопрос и (особенно) превосходная работа по его заданию, вместе с SSCCE и хорошим описанием как фактического, так и ожидаемого поведения. Отличная работа!   -  person Jerry Coffin    schedule 09.09.2013


Ответы (3)


Аргумент по умолчанию применяется к специализации, и фактически специализация должна принимать (так сказать) аргумент(ы) по умолчанию базового шаблона. Попытка указать значение по умолчанию в специализации:

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

template<class B=char>
// ...

... это ошибка.

Аналогичным образом, если мы изменим специализацию так, чтобы она относилась к типу отличному от стандартного, предоставленного базовым шаблоном:

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

template<class B>
class Base <char, B>

...тогда будет выбран базовый шаблон.

Итак, что происходит: сначала выбираются типы для аргументов шаблона. В этом случае (при создании экземпляра тип не указан) оба типа основаны на аргументах шаблона по умолчанию, указанных в базовом шаблоне.

Затем (как отдельный шаг) он выполняет аналог разрешения перегрузки для всех шаблонов, которые соответствуют этим типам аргументов. Как обычно для разрешения перегрузки, тип, указанный явно, предпочтительнее, чем тип, указанный неявно, поэтому ваша специализация (которая явно указывает int) предпочтительнее базового шаблона (который неявно указывает int).

person Jerry Coffin    schedule 09.09.2013
comment
Джерри, для вашего сведения, я разместил вопрос, который относится к заявлению, которое вы делаете здесь: "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": stackoverflow.com/questions/52583833/ - person Fabio; 01.10.2018

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

Здесь значения/инициализация по умолчанию для A и B были объявлены соответственно как int и double.

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

Здесь, в определениях классов, первый аргумент является чем-то вроде постоянного значения (здесь int; зачем объявлять таким образом, просто усложняя ситуацию? Лучше удалить первый аргумент шаблона), а второй аргумент шаблона — это B, значение по умолчанию которого — «двойное».

Base<> base;

Когда вы создаете объект класса. Хотя вы не указываете аргументы шаблона, компилятор принимает значения по умолчанию для аргументов (A и B), которые являются «int» и «double», и код выполняется без каких-либо ошибок или предупреждений.
Посмотрите, что происходит, когда вы создаете объект как:
Base<float,char> b; или Base<char,char> b;

person Sandeep Giri    schedule 09.09.2013
comment
Я думаю, вопрос в том, почему в данном случае выбрана частичная специализация, а не основной шаблон. Я не вижу этого в вашем ответе. - person Mat; 09.09.2013

Когда вы пишете Base<> base;, компилятор попытается выяснить, возможно ли создание экземпляра класса Base<>, если это возможно, код будет работать нормально. В этом случае это возможно из-за аргумента шаблона по умолчанию Base, потому что компилятор знает, если вы пишете Base<>, ему нужно создать объект Base<int,double>. то есть: из-за:

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

Так что код работает нормально.

person deeiip    schedule 09.09.2013
comment
Вопрос в том, почему это не должно фальшивить? @Сакшам - person deeiip; 09.09.2013
comment
это ответ на вопрос?? - person Saksham; 09.09.2013
comment
Поскольку указан аргумент по умолчанию, код будет работать. я думаю это ответ - person deeiip; 09.09.2013
comment
Этот ответ, насколько я могу судить, говорит, что текст не должен быть напечатан. - person chris; 09.09.2013
comment
@Крис почему так? где моя логика не будет верна? - person deeiip; 09.09.2013