Я хочу получить имя типа родителя, у которого есть определенный параметр (ключ) шаблона.
Например, если у меня есть родитель 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>
)?
Я не хочу использовать препроцессор для этого.
Чтобы избежать необходимости писать объявление 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