Специализация алиасом шаблонного параметра шаблона

#include <iostream>

template <template <typename> class>
struct A {
  A() { std::cout << '1'; }
};

template <typename>
struct X {};

template <typename T>
using Y = X<T>;

template <>
struct A<X> {
  A() { std::cout << '2'; }
};

int main() {
  A<X>{};
  A<Y>{};
}

Почему gcc последний выводит 22, а clang - 21? Как правильно и почему?


Ответы (1 шт):

Автор решения: tocic

clang прав, т.к. в соответствии со стандартом A<X> и A<Y> разные типы, gcc же считает их одинаковыми типами. Можно добавить специализацию для Y, чтобы проверить это.


Чтобы A<X> и A<Y> были одинаковыми, должны быть одинаковыми X и Y.

[temp.type]/1:

Two template-ids are the same if

  • their template-names, operator-function-ids, or literal-operator-ids refer to the same template, and
  • their corresponding type template-arguments are the same type, and
  • their corresponding non-type template-arguments are template-argument-equivalent (see below) after conversion to the type of the template-parameter, and
  • their corresponding template template-arguments refer to the same template.

Two template-ids that are the same refer to the same class, function, or variable.

Однако в стандарте нет пункта, который говорит о том, что шаблонный алиас Y эквивалентен шаблонному классу X. Есть только пункт про то, что некоторая специализация шаблонного алиаса эквивалентна соответствующему классу (т.е. Y<int> эквивалентно X<int>, но при этом Y не эквивалентно X).


Интересно, что одна из ранних версий C++11 стандарта содержала аналогичный пример, где было указано, что A<X> и A<Y> одинаковые типы. В связи с чем был опубликован CWG-1244. В ответ на эту проблему в окончательный вариант C++11 попал другой пример (вместо разрешения A<X> и A<Y> быть одним типом).

template<class T> struct X { };
template<class> struct Y { };
template<class T> using Z = Y<T>;
X<Y<int> > y;
X<Z<int> > z;

Это привело к публикации нового CWG-1286, который предлагал таки добавить в стандарт пункты, разрешающие исходный пример. Однако пока этот issue не закрыт и находится в активном состоянии (drafting).

→ Ссылка