创建变体交替值和值数组

use*_*329 5 c++ variadic-templates c++17

我想要类似的东西:

template <typename... Ts>
using make_variant_t = /* ??? */;
Run Code Online (Sandbox Code Playgroud)

例如,将其make_variant_t<Foo, Bar>评估为类型

 std::variant<Foo, std::vector<Foo>, Bar, std::vector<Bar>>
Run Code Online (Sandbox Code Playgroud)

按那个顺序。如果可能,如何实现?

Hol*_*Cat 5

干得好:

namespace impl
{
    template <typename R, typename ...P>
    struct make_variant {};

    template <typename ...R, typename P0, typename ...P>
    struct make_variant<std::variant<R...>, P0, P...>
    {
        using type = typename make_variant<std::variant<R..., P0, std::vector<P0>>, P...>::type;
    };

    template <typename ...R>
    struct make_variant<std::variant<R...>>
    {
        using type = std::variant<R...>;
    };
}

template <typename ...P>
using make_variant_t = typename impl::make_variant<std::variant<>, P...>::type;
Run Code Online (Sandbox Code Playgroud)

现在,make_variant_t<Foo, Bar>应扩展到std::variant<Foo, std::vector<Foo>, Bar, std::vector<Bar>>


Bar*_*rry 5

使用Boost.Mp11,这是一个简短的单行代码(一如既往):

template <typename... Ts>
using make_variant_t = mp_append<variant<Ts, vector<Ts>>...>;
Run Code Online (Sandbox Code Playgroud)

make_variant_t<int, char>首先会产生两个变体,variant<int, vector<int>>variant<char, vector<char>>。这些都是Mp11意义上的“列表”,并mp_append接收一堆列表并将它们连接在一起,从而按需生成variant<int, vector<int>, char, vector<char>>演示


Evg*_*Evg 3

std::tuple引擎盖下的替代解决方案:

namespace impl {
    template<class> struct tuple_to_variant;

    template<class... Ts>
    struct tuple_to_variant<std::tuple<Ts...>> {
        using type = std::variant<Ts...>;
    };
}

template<class... Ts>
using make_variant_t = typename impl::tuple_to_variant<decltype(    
    std::tuple_cat(std::declval<std::tuple<Ts, std::vector<Ts>>>()...))>::type;
Run Code Online (Sandbox Code Playgroud)