Вывести параметры шаблона для параметра шаблона std::variant

У меня есть класс шаблона, который принимает std::variant в качестве параметра шаблона:

template<class T>
class X
{
};

X<std::variant<int, float>> x;

Я хочу добавить ограничение на получение T из std::variant. Затем я хочу извлечь параметры шаблона этого варианта, чтобы использовать их внутри класса. Так:

template<class T, std::enable_if_t<
    std::is_base_of_v<std::variant<T::_Types>, T>, // _Types = int, float
bool> = true>
class X
{
    std::tuple<T::_Types> t; // std::tuple<int, float>
};

X<std::variant<int, float>> x;

Проблема в том, что я не могу получить эти параметры int, float из типа variant. Есть ли способ сделать это на С++ 17?

Этот вариант происходит от типа возвращаемого значения функции. Из-за этого я не могу вместо этого изменить его на что-то вроде параметров варианта (чтобы взять int, float напрямую).

Наследование от std::variant — не очень хорошая идея.

n. m. could be an AI 06.06.2024 11:46
std::variant_alternative и std::variant_size
perivesta 06.06.2024 11:51
Стоит ли изучать 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
2
74
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Признаки типа types_list предоставляют специализированный кортеж для различных типов, составляющих специализацию шаблонного класса T, в противном случае предоставляется пустой кортеж. Для простоты используется стандарт std::tuple.

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

Пример:

template <typename>
struct types_list
{ using type = std::tuple<>; };

template <template <typename...> typename T, typename ...Args>
struct types_list<T<Args...>>
{ using type = std::tuple<Args...>; };

template <typename T>
using types_list_t = typename types_list<T>::type;

С другой стороны, признак типа is_variant проверяет, является ли тип T специализацией std::variant.

Для реализации условия достаточно добавить частичную специализацию, которая принимает специализацию std::variant.

Пример:

template <typename>
struct is_variant
 : std::false_type {};

template <typename ...Args>
struct is_variant<std::variant<Args...>>
 : std::true_type {};

template <typename T>
inline constexpr bool is_variant_v = is_variant<T>::value;

Таким образом, класс можно перереализовать следующим образом.

template <typename T, typename = std::enable_if_t<is_variant_v<T>>>
class X
{
  types_list_t<T> t;
};

Итак, как я могу использовать это в своем примере? Мне нужен класс шаблона X<T>, который принимает variant<int, float> как T и может получить доступ к пакету параметров int, float внутри. Можете ли вы привести пример?

hopeless-programmer 07.06.2024 12:40

Как вы принимаете типы, производные от std::variant, и как извлекаете аргументы шаблона std::variant.

HolyBlackCat 07.06.2024 13:13

@HolyBlackCat, в комментарии ОП просит ограничить класс, чтобы он принял специализацию std::variant как T. Таким образом, я предоставляю частный случай экспериментальной черты типа is_specialization_of.

LoS 07.06.2024 13:17

Моя вина, упустил из виду этот момент.

HolyBlackCat 07.06.2024 13:31

Вы можете обобщить types_list, чтобы преобразовать его в любой другой шаблон: template <typename, template <typename...> typename T> struct types_list; template <template <typename...> typename In, typename ...Args, template <typename...> typename Out> struct types_list<In<Args...>, Out> { using type = Out<Args...>; };

Caleth 07.06.2024 15:08

@Калет, ты прав. Я также мог бы обобщить черту типа is_variant на is_specialization_of, но предпочел быть ближе к потребностям ОП.

LoS 07.06.2024 15:12

Чтобы получить родителя std::variant из производного от него класса (если я вас правильно понимаю, вы тоже хотите принимать производные классы), сделайте следующее:

template <typename ...P>
std::variant<P...> &VariantIdentity(std::variant<P...> &);

template <typename T>
using ToBaseVariant = std::remove_reference_t<decltype((VariantIdentity)(std::declval<T &>()))>;

Затем вы можете извлечь аргументы из варианта, используя частичную специализацию. Например. базового класса X или, как предполагает другой ответ, совершенно отдельного класса.

template <typename T>
class XBase;

template <typename ...P>
class XBase<std::variant<P...>>
{
    std::tuple<P...> t;
};

template <typename T>
class X : XBase<ToBaseVariant<T>>
{
    using XBase<ToBaseVariant<T>>::XBase;
};

Как реализована функция VariantIdentity()? Возвращает ли он входную ссылку без изменений?

LoS 10.06.2024 11:16

@LoS У него нет реализации. Ему это не нужно, потому что он вызывается только внутри decltype.

HolyBlackCat 10.06.2024 11:20

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