Странное поведение is_same_template для псевдонимов шаблона
Следующая программа...
#include <iostream>
#include <type_traits>
template <typename T>
struct Template{};
template <typename T>
using Alias = Template<T>;
template
<
template <typename>
class T1,
template <typename>
class T2
>
struct is_same_template : std::false_type{};
template
<
template <typename>
class T
>
struct is_same_template<T, T> : std::true_type{};
int main() {
std::cout << std::boolalpha;
std::cout << "Template == Template: " << is_same_template<Template, Template>::value << std::endl;
std::cout << "Template == Alias: " << is_same_template<Template, Alias>::value << std::endl;
std::cout << "Alias == Alias: " << is_same_template<Alias, Alias>::value << std::endl;
}
... выход...
Template == Template: true
Template == Alias: false
Alias == Alias: true
... скомпилировано с g ++ 4.8.1, clang 3.4 и vC++ 18.00.21005.1.
Это ошибка в этих компиляторах или требование стандарта?
1 ответ
Такое поведение требуется Стандартом, и оно вполне логично. Шаблон псевдонима не является псевдонимом шаблона (несмотря на то, что некоторые его предполагают). Первоначально, по-видимому, даже в стандарте возникла путаница по этому поводу, см. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html.
В текущей стандартизированной форме шаблон псевдонима похож на его не шаблонную встречную часть: он псевдоним типа. В версии шаблона тип может быть зависимым.
И это сразу подставляется. Например Alias<T>
с T
Сам по себе параметр шаблона будет зависимым типом Template<T>
- в этом смысле шаблон псевдонима имени может быть немного запутанным, потому что он предполагает, что в какой-то момент будет создано объявление псевдонима. Но на самом деле шаблон псевдонима заменяется немедленно - в этом смысле шаблонная версия больше похожа на объявление зависимого псевдонима, которое всегда существует и не нуждается в создании экземпляра, а не является шаблоном объявления псевдонима.
В связи с этим становится немного философским, что именно мы подразумеваем под этими терминами.