Как сопоставить тип оболочки с типами в варианте
Предположим, у меня есть такой код:
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.