Является ли шаблон псевдонима тем же параметром шаблона шаблона, что и исходный шаблон?

Играясь, я наткнулся на следующий фрагмент кода, который на удивление не соответствует моим ожиданиям.

#include <tuple>
#include <type_traits>

template <class... Ts>
using myTuple = std::tuple<Ts...>;

template <template <class...> class Lhs, template <class...> class Rhs>
struct is_same
    : public std::false_type
{};

template <template <class...> class T>
struct is_same<T, T>
    : public std::true_type
{};

int main() {
    static_assert(is_same<myTuple, std::tuple>::value, "not same");
}

Я закинул его на godbolt и попытался скомпилировать тремя разными компиляторами (clang, msvc и gcc) и получил смешанные результаты.

лязг:

<source>:18:5: error: static_assert failed due to requirement 'is_same<myTuple, std::tuple>::value' "not same"
static_assert(is_same<myTuple, std::tuple>::value, "not same");
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

МСВК:

<source>(18): error C2338: static_assert failed: 'not same'

gcc:

(no errors)

Теперь я задаюсь вопросом, какое поведение является правильным? Я ожидаю, что оба аргумента одинаковы, и поэтому используется специализация, потому что псевдонимы обычно не отличаются от исходного типа. Если это не правильный аргумент здесь, я хотел бы знать, почему.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

GCC ошибается в этом, а Clang и MSVC правы. static_assert должен потерпеть неудачу.

myTuple не является псевдонимом шаблона std::tuple. Псевдонимов для шаблонов нет, только для типов.

std::tuple и myTuple — это два разных шаблона, один из которых является шаблоном класса, а другой — шаблоном псевдонима. Шаблоны псевдонимов не называются так, потому что они являются псевдонимами других шаблонов. Их так называют потому что каждая специализация шаблона псевдонима является псевдонимом (типа).

То, что каждая специализация двух шаблонов с одним и тем же списком аргументов шаблона приводит к тому, что что-то ссылается на один и тот же тип, здесь не должно иметь значения. Вывод по перегрузке true должен завершиться ошибкой при выводе двух разных значений (т. е. шаблонов) для T.

Но см., например. открытый (но старый) CWG issue 1286 , в котором рассматривается возможность сделать определенные шаблоны псевдонимов формы, которую вы используете, эквивалентными шаблону класса, используемому в его определении. Я предполагаю, что это также должно повлиять на вывод аргумента шаблона, чтобы рассмотреть два значения, выведенные для T, «согласованные». Эта проблема также связана с решенной проблемой CWG 1244, которая подтверждает, что псевдоним и шаблон класса не эквивалентны и поэтому (я бы сказал) также не «согласованы» с целью вывода аргументов шаблона.

@AdrianMole Нет, все компиляторы (или, по крайней мере, GCC и Clang, которые я могу протестировать) согласны с тем, что это std::is_same<myTuple, std::tuple>::value неправильно сформировано, а не с тем, что оно ложно. ОП пришлось сворачивать свои собственные is_same, поскольку std::is_same может сравнивать только типы, а не шаблоны.

HTNW 18.04.2023 21:50

Другие вопросы по теме