File: move_from_tuple.hpp

package info (click to toggle)
reflect-cpp 0.18.0%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 12,524 kB
  • sloc: cpp: 44,484; python: 131; makefile: 30; sh: 3
file content (136 lines) | stat: -rw-r--r-- 3,898 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#ifndef RFL_MOVE_FROM_TUPLE_HPP_
#define RFL_MOVE_FROM_TUPLE_HPP_

#include <functional>
#include <type_traits>

#include "../Tuple.hpp"
#include "../tuple_cat.hpp"
#include "Array.hpp"
#include "is_flatten_field.hpp"
#include "is_named_tuple.hpp"
#include "ptr_tuple_t.hpp"
#include "tup_to_ptr_tuple.hpp"
#include "tuple_t.hpp"

namespace rfl {
namespace internal {

template <class Tuple, int _i = 0>
constexpr int calc_flattened_size() {
  if constexpr (_i == rfl::tuple_size_v<Tuple>) {
    return 0;
  } else {
    using T = std::remove_pointer_t<tuple_element_t<_i, Tuple>>;
    if constexpr (is_flatten_field_v<T>) {
      return calc_flattened_size<ptr_tuple_t<typename T::Type>>() +
             calc_flattened_size<Tuple, _i + 1>();
    } else {
      return 1 + calc_flattened_size<Tuple, _i + 1>();
    }
  }
}

// TODO: Non-recursive implementation
template <class TargetTupleType, class PtrTupleType, int _j = 0, class... Args>
auto unflatten_ptr_tuple(PtrTupleType& _t, Args... _args) {
  constexpr auto i = sizeof...(Args);

  constexpr auto size = rfl::tuple_size_v<std::remove_cvref_t<TargetTupleType>>;

  if constexpr (i == size) {
    return rfl::make_tuple(_args...);
  } else {
    using T = std::remove_cvref_t<
        std::remove_pointer_t<tuple_element_t<i, TargetTupleType>>>;

    if constexpr (is_flatten_field_v<T>) {
      using SubTargetTupleType =
          ptr_tuple_t<std::remove_pointer_t<typename T::Type>>;

      constexpr int flattened_size = calc_flattened_size<SubTargetTupleType>();

      return unflatten_ptr_tuple<TargetTupleType, PtrTupleType,
                                 _j + flattened_size>(
          _t, _args...,
          unflatten_ptr_tuple<SubTargetTupleType, PtrTupleType, _j>(_t));

    } else {
      return unflatten_ptr_tuple<TargetTupleType, PtrTupleType, _j + 1>(
          _t, _args..., std::get<_j>(_t));
    }
  }
}

template <class T, class Pointers, class... Args>
auto move_from_pointers(Pointers& _ptrs, Args&&... _args) {
  constexpr auto i = sizeof...(Args);
  if constexpr (i == rfl::tuple_size_v<std::remove_cvref_t<Pointers>>) {
    return std::remove_cvref_t<T>{std::move(_args)...};
  } else {
    using FieldType = tuple_element_t<i, std::remove_cvref_t<Pointers>>;

    if constexpr (std::is_pointer_v<FieldType>) {
      return move_from_pointers<T>(_ptrs, std::move(_args)...,
                                   std::move(*std::get<i>(_ptrs)));

    } else {
      using PtrTupleType = ptr_tuple_t<std::remove_cvref_t<T>>;

      using U = std::remove_cvref_t<typename std::remove_pointer_t<
          tuple_element_t<i, PtrTupleType>>::Type>;

      return move_from_pointers<T>(_ptrs, std::move(_args)...,
                                   move_from_pointers<U>(std::get<i>(_ptrs)));
    }
  }
}

template <class T>
auto flatten_array(T* _v) {
  return rfl::make_tuple(_v);
}

template <class T, std::size_t _n>
auto flatten_array(std::array<T, _n>* _arr) {
  const auto fct = [](auto&... _v) {
    return rfl::tuple_cat(flatten_array(&_v)...);
  };
  return std::apply(fct, *_arr);
}

template <class T>
auto make_tuple_from_element(T _v) {
  return rfl::make_tuple(_v);
}

template <class T>
auto make_tuple_from_element(Array<T>* _arr) {
  return flatten_array(&(_arr->arr_));
}

auto flatten_c_arrays(const auto& _tup) {
  const auto fct = [](auto... _v) {
    return rfl::tuple_cat(make_tuple_from_element(_v)...);
  };
  return rfl::apply(fct, _tup);
}

/// Creates a struct of type T from a tuple by moving the underlying
/// fields.
template <class T, class TupleType>
auto move_from_tuple(TupleType&& _t) {
  auto ptr_tuple = tup_to_ptr_tuple(_t);

  using TargetTupleType = tuple_t<std::remove_cvref_t<T>>;

  auto pointers =
      flatten_c_arrays(unflatten_ptr_tuple<TargetTupleType>(ptr_tuple));

  return move_from_pointers<T>(pointers);
}

}  // namespace internal
}  // namespace rfl

#endif