Подтвердить что ты не робот

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

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

#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?

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Таким образом, код работает нормально.

Ответ 3

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

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

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

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

Base<> base;

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