Идентичная полная специализация шаблона

Каков правильный синтаксис для полной специализации класса шаблона по уже определенной специализации?

Например, как в приведенном ниже коде объявить A<2> псевдонимом A<0>?

template <int I>
struct A;

template <>
struct A<0> { int x; };

template <>
struct A<1> { int y; };

template <>
using A<2> = A<0>; // error: expected unqualified-id before 'using'

Примечание: для приведенного выше кода было бы достаточно специализировать A<1> и определить неспециализированные A как A<0>:

template <int I>
struct A { int x; };

template <>
struct A<1> { int y; };

но это не сработает, если у вас более сложная ситуация, когда для набора значений у вас есть специализация, для другого набора значений другая специализация и т. д.

Нельзя сделать так, чтобы struct вдруг стал псевдонимом для какой-то специализации. Это похоже на проблему XY.

Marek R 13.01.2023 10:55

@463035818_is_not_a_number да, я бы хотел A<2> быть именно A<0>

francesco 13.01.2023 10:56

@ 463035818_is_not_a_number Теперь, когда я подумал об этом, я думаю, что мог бы сначала определить структуры, реализующие нужные мне специализации, а затем переключить значения параметра шаблона, как в этом ответе

francesco 13.01.2023 11:09

@francsesco да, в основном это так. Разница только в деталях, как вы можете видеть в ответах

463035818_is_not_a_number 13.01.2023 11:23
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
58
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Не уверен, что понял вашу проблему, так как вы описали ее своей попыткой решить.

Вот мой подход к достижению аналогичного результата:

struct Ax { int x; };

struct Ay { int y; };

template <int I>
struct Aselector;

template<>
struct Aselector<0>{
    using type = Ax;
};

template<>
struct Aselector<1>{
    using type = Ay;
};

template<>
struct Aselector<2>{
    using type = Ax;
};

template <int I>
using A = typename Aselector<I>::type;

https://godbolt.org/z/fGxcoE5xd

Версия с использованием типажей короче:

#include <type_traits>

struct Ax { int x; };

struct Ay { int y; };

template <int I>
using A = std::conditional_t<I == 1, Ay, std::enable_if_t<I >= 0 && I <= 2, Ax>>;

https://godbolt.org/z/vMqPahfEo

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

более сложная ситуация, когда для набора значений у вас есть специализация, для другого набора значений другая специализация и т.д...

Здесь может помочь уровень косвенности.

#include <iostream>
#include <type_traits>

template <size_t I> struct selector { static const size_t value = I; };    
template <> struct selector<2> { static const size_t value = 0;};
    
template <size_t J> struct Foo_impl { int x; };
template <> struct Foo_impl<1> { int y; };

template <size_t I> using Foo = Foo_impl< selector<I>::value >;
    
int main() {
    std::cout << std::is_same_v< Foo<0> , Foo<2> > << "\n";
    
    Foo<0> f0;
    f0.x = 42;
    Foo<1> f1;
    f1.y = 0;
    Foo<2> f2;
    f2.x = 123;
}

Foo<0> и Foo<2> одного типа. Вы можете добавить больше специализаций в Foo_impl и добавить больше сопоставлений между аргументом шаблона I и фактическим индексом специализации J.

Другие ответы должны работать, я просто хотел предложить решение на основе SFINAE:

#include <iostream>

template <int I, typename = void>
struct A;

template <int I>
struct A<I, std::enable_if_t<I == 0 || I == 2>> { int x; };

template <typename Conditional>
struct A<1, Conditional> { int y; };

int main()
{
    std::cout << A<0>{}.x << std::endl;
    std::cout << A<1>{}.y << std::endl;
    std::cout << A<2>{}.x << std::endl;


    return 0;
}

Предостережение: хотя этот код позволяет A<0> и A<2> совместно использовать реализацию, они не будут идентичными типами. Например: std::is_same_v<A<0>, A<2>> вернет true для других ответов, но false для этого.

ваш A<0> не псевдоним для A<2>, это два разных типа

463035818_is_not_a_number 13.01.2023 11:26

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

Wutz 13.01.2023 11:33

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

Как вызвать одну из двух шаблонных функций C++ с условием
Шаблон псевдонима с переключением параметров шаблона
Как я могу заменить ключевое слово автоматической ссылки в этом коде?
Разрешение перегрузки для шаблонов функций с автоматическим параметром шаблона, отличным от типа
Руководство по выводу шаблона не работает с лямбда, но не с глобальной функцией
Как добавить специализацию шаблона для универсального метода в универсальном классе, когда два типа равны?
Как вывести аргумент шаблона при сохранении класса с лямбда-шаблоном в качестве члена другого класса?
C++: функция шаблона, принимающая функцию, которая принимает другую функцию, которая использует ссылку на тип шаблона в качестве параметра
Использование рекурсивных параметров шаблона с переменным числом аргументов в возвращаемом типе функции
Нет функции сопоставления для лямбда со ссылочным аргументом