Как специализации шаблона соответствуют нетиповым аргументам разных типов и есть ли разница между классами и псевдонимамC++

Программы на C++. Форум разработчиков
Anonymous
 Как специализации шаблона соответствуют нетиповым аргументам разных типов и есть ли разница между классами и псевдонимам

Сообщение Anonymous »

Следующая программа определяет класс A с нетиповым шаблонным аргументом типа long.
Это можно создать, передав 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
Я пытался скомпилировать приведенный выше код на Godbolt и ожидал, по крайней мере, последовательного поведения во всех случаях. clang последовательно принимает все регистры (версии с 10.0.0 по 19.1.0). Но gcc завершается сбоем, когда аргументом свойства типа является int (версии с 10.1 по 14.2), а также gcc версии 14.* завершается с ошибкой, когда тип, который мы тестируем, является псевдонимом типа.


Подробнее здесь: https://stackoverflow.com/questions/790 ... -types-and

Вернуться в «C++»