Как сопоставить тип оболочки с типами в варианте

Предположим, у меня есть такой код:

      
template<typename T>
struct wrapper {};

using my_variant = std::variant<int, bool>;

using my_wrapped = // should resolve to std::variant<wrapper<int>, wrapper<bool>>, by adding wrapper to each element of my_variant

1 ответ

Мы можем сделать это с помощью вывода аргумента шаблона:

      #include <variant>

template<template<typename...> class V, typename... Vargs>
struct map_inner {
    map_inner(const V<Vargs...>&){}

    template<template<typename> class Wrap>
    using type = V<Wrap<Vargs>...>;
};

template<template<typename...> class V, typename... Vargs>
map_inner<V, Vargs...> make_inner(const V<Vargs...>& v) {
    return map_inner<V, Vargs...>{v};
}

template<typename T>
struct my_wrapper {};

using my_variant = std::variant<int, bool>;

using my_wrapped_variant_cpp17 = typename decltype(map_inner{std::declval<my_variant>()})::type<my_wrapper>; // c++17 version

using my_wrapped_variant_cpp11 = typename decltype(make_inner(std::declval<my_variant>()))::type<my_wrapper>;

static_assert(std::is_same_v<std::variant<my_wrapper<int>, my_wrapper<bool>>, my_wrapped_variant_cpp11>);
static_assert(std::is_same_v<std::variant<my_wrapper<int>, my_wrapper<bool>>, my_wrapped_variant_cpp17>);

Обратите внимание, что версия more c++17 использует CTAD , чтобы устранить необходимость в функции-оболочке, которая делает вывод за нас.

Это также работает для типов, отличных от std::variant, такие как std::tuple.

Этот код основан на выражениях свертки С++17, поэтому я не думаю, что он будет работать с С++ 11, хотя я включил версию, которая все равно использует меньше концепций С++17.

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