递归地将 std::tuple 转换为 std::variant
Convert std::tuple to std::variant recursively
需要了解使用什么技术来递归地声明包含给定 std::tuple
及其子元组(如果元素也是元组)中包含的所有类型的 std::variant
类型。
例如,
std::tuple<int, std::tuple<int, double, std::tuple<float, double, std::string>>>
转变为
std::variant<int, double, float, std::string>
简而言之,我需要将所有唯一类型包含在 std::variant
中。
有了 Boost.Mp11,还不错。
第一步是递归地展平输入列表。我们有 mp_flatten
,但这只会进行一次展平 - 我们需要递归调用它。可能有更好的方法来做到这一点,但到目前为止我想出的最好的方法是使用 mp_iterate
和一个只有在执行某些操作时才会展平的函数:
// maybe_flatten succeeds only if it actually flattens
// (once we're flat, it's ill-formed, we use that a terminating condition for mp_iterate)
template <typename L,
typename U=mp_flatten<L>,
typename = std::enable_if_t<not mp_same<L, U>::value>>
using maybe_flatten = U;
template <typename L>
using recursive_flatten = mp_back<mp_iterate<L, mp_identity_t, maybe_flatten>>;
一旦我们有了 recursive_flatten
,那么我们需要做的就是确保类型是唯一的并将其重命名为变体:
template <typename L>
using to_variant = mp_rename<mp_unique<recursive_flatten<L>>, std::variant>;
Demo.
我在这里试验了线程元函数(Clojure 的 ->
),这样您就可以编写按顺序调用的函数。我不确定它是否更好:
template <typename L>
using recursive_flatten2 = thread<
mp_iterate<L, mp_identity_t, maybe_flatten>,
mp_back>;
template <typename L>
using to_variant2 = thread_q<
L,
mp_quote<recursive_flatten2>,
mp_quote<mp_unique>,
mp_bind_q<mp_quote<mp_apply_q>, mp_quote<std::variant>, _1>
>;
需要了解使用什么技术来递归地声明包含给定 std::tuple
及其子元组(如果元素也是元组)中包含的所有类型的 std::variant
类型。
例如,
std::tuple<int, std::tuple<int, double, std::tuple<float, double, std::string>>>
转变为
std::variant<int, double, float, std::string>
简而言之,我需要将所有唯一类型包含在 std::variant
中。
有了 Boost.Mp11,还不错。
第一步是递归地展平输入列表。我们有 mp_flatten
,但这只会进行一次展平 - 我们需要递归调用它。可能有更好的方法来做到这一点,但到目前为止我想出的最好的方法是使用 mp_iterate
和一个只有在执行某些操作时才会展平的函数:
// maybe_flatten succeeds only if it actually flattens
// (once we're flat, it's ill-formed, we use that a terminating condition for mp_iterate)
template <typename L,
typename U=mp_flatten<L>,
typename = std::enable_if_t<not mp_same<L, U>::value>>
using maybe_flatten = U;
template <typename L>
using recursive_flatten = mp_back<mp_iterate<L, mp_identity_t, maybe_flatten>>;
一旦我们有了 recursive_flatten
,那么我们需要做的就是确保类型是唯一的并将其重命名为变体:
template <typename L>
using to_variant = mp_rename<mp_unique<recursive_flatten<L>>, std::variant>;
Demo.
我在这里试验了线程元函数(Clojure 的 ->
),这样您就可以编写按顺序调用的函数。我不确定它是否更好:
template <typename L>
using recursive_flatten2 = thread<
mp_iterate<L, mp_identity_t, maybe_flatten>,
mp_back>;
template <typename L>
using to_variant2 = thread_q<
L,
mp_quote<recursive_flatten2>,
mp_quote<mp_unique>,
mp_bind_q<mp_quote<mp_apply_q>, mp_quote<std::variant>, _1>
>;