Специализация алиасом шаблонного параметра шаблона
#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 шт):
clang прав, т.к. в соответствии со стандартом A<X> и A<Y> разные типы, gcc же считает их одинаковыми типами. Можно добавить специализацию для Y, чтобы проверить это.
Чтобы A<X> и A<Y> были одинаковыми, должны быть одинаковыми X и Y.
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).