gpt4 book ai didi

C++ 使嵌套元组 "plain"/"flatten"

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:35:39 27 4
gpt4 key购买 nike

问题:使元组的元组“简单”的最佳方法是什么?例如。一维。

案例 1

template <class Field>
auto process_field(Field&& field){
// or another std::get<ids>(field)...
return std::forward_as_tuple(field.fst, field.snd, field.thrd, field.fth);
}

template <std::size_t ...ids, class Rec>
auto iterate_record(std::index_sequence<ids...>, Rec && rec){
return forward_as_tuple(
process_field
(std::get<ids>( forward<Rec>(rec).data))...
);
}

iterate_record返回元组的元组。我需要普通元组。

也许我需要某种包装 iterate_record ,或直接围绕此:process_field (std::get<ids>( forward<Rec>(rec).data))...


案例 2

我有一个元组的元组(具体类型,而不是引用)。如何高效复制到普通版?

最佳答案

这是我的看法。

首先,一个包装器,需要它来正确处理包含源元组和元素上的引用和 cv 限定的元组。我们存储 1) 这个包装器应该解包成的类型; 2) 我们是否可以从源头上移动。

template<class U, class T, bool can_move>
struct wrapper {
T* ptr;
wrapper(T& t) : ptr(std::addressof(t)) {}

using unwrapped_type =
std::conditional_t<can_move,
std::conditional_t<std::is_lvalue_reference<U>{}, T&, T&&>,
std::conditional_t<std::is_rvalue_reference<U>{}, T&&, T&>>;
using tuple_element_type = U;

unwrapped_type unwrap() const{
return std::forward<unwrapped_type>(*ptr);
}
};

接下来,一个解包包装元组的函数:

template<class... Wrappers, std::size_t... Is>
auto unwrap_tuple(const std::tuple<Wrappers...>& t, std::index_sequence<Is...>) {
return std::tuple<typename Wrappers::tuple_element_type...>(std::get<Is>(t).unwrap()...);
}

template<class... Wrappers>
auto unwrap_tuple(const std::tuple<Wrappers...>& t) {
return unwrap_tuple(t, std::index_sequence_for<Wrappers...>());
}

现在将一个(可能嵌套的)元组转换为扁平的包装器元组。这与 Piotr 的 explode 非常相似:

template<bool can_move, class V, class T>
auto wrap_and_flatten(T& t, char){
return std::make_tuple(wrapper<V, T, can_move>(t));
}
template<class T> struct is_tuple : std::false_type {};
template<class... Ts> struct is_tuple<std::tuple<Ts...>> : std::true_type {};
template<class T> struct is_tuple<const T> : is_tuple<T> {};
template<class T> struct is_tuple<volatile T> : is_tuple<T> {};

template<bool can_move, class, class Tuple,
class = std::enable_if_t<is_tuple<std::decay_t<Tuple>>{}>>
auto wrap_and_flatten(Tuple& t, int);

template<bool can_move, class Tuple, std::size_t... Is>
auto wrap_and_flatten(Tuple& t, std::index_sequence<Is...>) {
return std::tuple_cat(wrap_and_flatten<can_move, std::tuple_element_t<Is, std::remove_cv_t<Tuple>>>(std::get<Is>(t), 0)...);
}

template<bool can_move, class V, class Tuple, class>
auto wrap_and_flatten(Tuple& t, int) {
using seq_type = std::make_index_sequence<std::tuple_size<Tuple>{}>;
return wrap_and_flatten<can_move>(t, seq_type());
}

template<class Tuple>
auto wrap_and_flatten_tuple(Tuple&& t){
constexpr bool can_move = !std::is_lvalue_reference<Tuple>{};
using seq_type = std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>{}>;
return wrap_and_flatten<can_move>(t, seq_type());
}

最后,将它们放在一起 - 包裹、展平,然后展开:

template <typename T>
auto merge_tuple(T&& t)
{
return unwrap_tuple(wrap_and_flatten_tuple(std::forward<T>(t)));
}

Demo .

关于C++ 使嵌套元组 "plain"/"flatten",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32165999/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com