Вывести полный тип родителя из одного из его параметров шаблона

Я хочу получить имя типа родителя, у которого есть определенный параметр (ключ) шаблона.

Например, если у меня есть родитель MyParent<int, 1>, я хочу иметь возможность получить этот тип (MyParent<int, 1>) от своего дочернего элемента всего с «1». Если у меня есть MyParent<float,2>, я хочу получить этот тип (MyParent<float, 2>) всего за «2».

По сути, я хочу получить имя типа (MyParent<float, 1>, MyParent<int, 2> и т. д.) из «ключа» (1, 2, 3 и т. д.)

Я использую компилятор MSVC в режиме C++20.

Вот рабочий код, который делает именно это (но у него есть один недостаток):

#include <iostream>

template<std::size_t key>
class KeyClass {};

template<class Type, std::size_t key>
class parent
{
    using keyclass = KeyClass<key>;
    using self = parent<Type, key>;
public:
    template<std::same_as<keyclass> T>
    static self GetType() {}
};

class test :
    public parent<int, 1>,
    public parent<float, 2>
{
public:
    using parent<int, 1>::GetType;
    using parent<float, 2>::GetType;
};

int main()
{
    std::cout << typeid(decltype(test::GetType<KeyClass<1>>())).name() << std::endl;
    std::cout << typeid(decltype(test::GetType<KeyClass<2>>())).name() << std::endl;
}

Это печатает, как и ожидалось: «class parent<int,1> class parent<float,2>». Я могу свободно использовать эти типы, получать их статические члены и делать с ними другие вещи, и это именно то, что я хочу.

Недостатком является то, что я должен явно указать, что я использую метод GetType от каждого из моих родителей. Что довольно хромает, так как мне приходится вводить все дважды (наследование один раз, а затем указание «использование»). Представьте, что у вас есть десятки ключей...

Есть ли другие способы сделать это, не повторяя мой код? Например, есть ли способ указать «используя GetType» для все родителей в одной строке? Или сделать их автоматически унаследованными или что-то в этом роде, чтобы мне вообще не нужно было указывать «использование»?

Или, может быть, есть другой способ сделать то, что я хочу (получить тип во время компиляции из какого-то ключа (параметра шаблона), например, 1 должен вернуть Myparent<int, 1>, 2 должен вернуть MyParent<int, 2>)?

Я не хочу использовать препроцессор для этого.

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
40
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Чтобы избежать необходимости писать объявление using для членов каждого из родительских классов, вы можете написать оболочку шаблона класса с переменным числом переменных, которая предоставляет этот элемент для всех типов (как в шаблоне Overloader, показанном здесь).

template<typename... Ts>
struct Bases : Ts...
{
    using Ts::GetType...; 
};

И теперь ваш класс test может просто наследоваться от этой оболочки как

class test : public Bases<parent<int, 1>, 
                          parent<float, 2>>
{};

Вот демо

Спасибо, работает как шарм. Если кому-то интересно, вот пример того, чего я хотел добиться с помощью этого кода: godbolt.org/z/qsqexK4xr

bIu9d10qnSQfoxwfuMc3 21.03.2022 15:28

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