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)
按那个顺序。如果可能,如何实现?
干得好:
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>>
。
使用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>>
。演示。
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)