Это можно создать, передав int значение, что, конечно, разрешено, поскольку int может быть неявно преобразовано в long.
Теперь я определяю признак типа Is_A_1 для идентификации специализация А. Поэтому я определяю основной шаблон, производный от std::false_type, и специализацию, принимающую нетипичный аргумент шаблона auto x, соответствующий A и производный от std: :true_type. Это работает, например. Is_A_1::value имеет значение true.
Затем я определяю Is_A_2, который является небольшой вариацией Is_A_1. Аргументом шаблона, не относящимся к типу, для специализации является int x вместо auto x. Это компилируется в clang, но не в gcc (все версии поддерживают C++20).
Затем я определяю шаблон псевдонима типа , используя B = A и определите признаки типа Is_B_1 и Is_B_2 аналогично Is_A_1 и Is_A_2. Они ведут себя одинаково во всех версиях компилятора, за исключением gcc 14, Is_B_1 имеет значение false.
Моя интуиция подсказывает, что clang прав, а gcc нет, потому что все случаи настолько похожи, что я чувствую, что они должны дать один и тот же ответ, но это просто интуиция.
На https://en.cppreference.com/w/cpp/language/ template_parameters, раздел «Аргументы, не относящиеся к шаблону», там говорится:
Если T содержит тип-заполнитель или является заполнителем для выведенного типа класса, тип параметра шаблона — это тип, выведенный для переменной x в изобретенном объявлении T x = E;, где E — это аргумент шаблона, предоставленный для параметра.
Для меня это звучит так, как будто тип аргумента auto выводится из контекста, а контекстом является значение int 7. Это заставляет меня думать, что по крайней мере Is_A_1::value должно быть равно Is_A_2::value, а Is_B_1::value должно быть равно Is_B_2>::value.
Но затем gcc изменил поведение в более высокой версии, сделав его более строгим для псевдонимов типов. Поскольку время движется вперед, и чем новее, тем лучше, я задаюсь вопросом, правильнее ли более строгое поведение? Но я просто предполагаю.
Описано ли в стандарте поведение в этих случаях?
Код: Выделить всё
#include // std::false_type
template class A {};
A a; // OK
template struct Is_A_1 : public std::false_type {};
template struct Is_A_1 : public std::true_type {};
static_assert(Is_A_1::value); // OK
template struct Is_A_2 : public std::false_type {};
template struct Is_A_2 : public std::true_type {};
static_assert(Is_A_2::value); // Error in gcc, OK in clang
template using B = A;
B b; // OK
template struct Is_B_1 : public std::false_type {};
template struct Is_B_1 : public std::true_type {};
static_assert(Is_B_1::value); // OK everywhere except gcc 14
template struct Is_B_2 : public std::false_type {};
template struct Is_B_2 : public std::true_type {};
static_assert(Is_B_2::value); // Error in gcc, OK in clang
Подробнее здесь: https://stackoverflow.com/questions/790 ... -types-and