File: field_type.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 (65 lines) | stat: -rw-r--r-- 2,123 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
#ifndef RFL_INTERNAL_FIELD_TYPE_HPP_
#define RFL_INTERNAL_FIELD_TYPE_HPP_

#include <tuple>
#include <type_traits>
#include <variant>

#include "../NamedTuple.hpp"
#include "../TaggedUnion.hpp"
#include "../Tuple.hpp"
#include "../named_tuple_t.hpp"
#include "StringLiteral.hpp"
#include "find_index.hpp"

namespace rfl {
namespace internal {

template <class T, class... Ts>
struct are_same : std::conjunction<std::is_same<T, Ts>...> {};

/// Finds the type of the field signified by _field_name
template <StringLiteral _field_name, class T>
struct FieldType;

/// Default option - for named tuples.
template <StringLiteral _field_name, class T>
struct FieldType {
  using NamedTupleType = named_tuple_t<T>;

  static constexpr int field_ix_ =
      internal::find_index<_field_name, typename NamedTupleType::Fields>();

  using Type = typename tuple_element_t<field_ix_,
                                        typename NamedTupleType::Fields>::Type;
};

/// For variants - in this case the FieldType returned by all options must be
/// the same.
template <StringLiteral _field_name, class FirstAlternativeType,
          class... OtherAlternativeTypes>
struct FieldType<_field_name,
                 std::variant<FirstAlternativeType, OtherAlternativeTypes...>> {
  constexpr static bool all_types_match = std::conjunction_v<std::is_same<
      typename FieldType<_field_name, FirstAlternativeType>::Type,
      typename FieldType<_field_name, OtherAlternativeTypes>::Type>...>;

  static_assert(all_types_match, "All field types must be the same.");

  using Type = typename FieldType<_field_name, FirstAlternativeType>::Type;
};

/// For tagged union - just defers to the variant.
template <StringLiteral _field_name, StringLiteral _discriminator_name,
          class... VarTypes>
struct FieldType<_field_name, TaggedUnion<_discriminator_name, VarTypes...>> {
  using Type =
      typename FieldType<_field_name,
                         typename TaggedUnion<_discriminator_name,
                                              VarTypes...>::VariantType>::Type;
};

}  // namespace internal
}  // namespace rfl

#endif