-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstance.hpp
117 lines (104 loc) · 3.93 KB
/
instance.hpp
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
#pragma once
#include "auto_definition.hpp"
#include "matchbuilder.hpp"
#include "mutils/macro_utils.hpp"
namespace compile_time {
namespace value {
template <typename T> struct convert_to_instance;
template <typename T> struct permitted_raw;
} // namespace value
namespace specification {
template <typename client> struct user_definition;
}
namespace value {
template <typename client> struct auto_definition;
template <typename client>
using definition = std::conditional_t<
mutils::is_defined_v<specification::user_definition<client>>,
specification::user_definition<client>, auto_definition<client>>;
template <typename client> struct instance : public definition<client> {
constexpr instance() = default;
constexpr instance(instance &&) = default;
constexpr instance(const instance &) = default;
CONSTVARY(template <typename... args> constexpr auto match(args &&... a), {
return matchBuilder<struct_size<client>, client>::match(
*this, std::forward<args>(a)...);
})
using num_fields = std::integral_constant<std::size_t, struct_size<client>>;
using field_index_sequence = std::make_index_sequence<num_fields::value>;
using client_t = client;
constexpr instance &operator=(const instance &o) = default;
constexpr instance &operator=(instance &&o) = default;
private:
// field offset translations
template <std::size_t... indices>
static constexpr std::size_t
translate_field(std::size_t in, std::size_t offset_so_far,
std::integer_sequence<std::size_t, indices...> *ptr) {
static_assert(sizeof...(indices) == num_fields::value,
"Internal error: call to translate_field");
constexpr std::size_t field_sizes[num_fields::value] = {
sizeof(boost::pfr::tuple_element_t<indices, client>)...};
if (in == 0)
return offset_so_far;
else {
return translate_field(in - field_sizes[offset_so_far], offset_so_far + 1,
ptr);
}
}
public:
template <std::size_t in> constexpr decltype(auto) get_by_offset() {
constexpr field_index_sequence *choice{nullptr};
return this->template get<translate_field(in, 0, choice)>();
}
template <std::size_t in> constexpr decltype(auto) get_by_offset() const {
constexpr field_index_sequence *choice{nullptr};
return this->template get<translate_field(in, 0, choice)>();
}
private:
// the gets
template <std::size_t N>
constexpr decltype(auto) get(specification::user_definition<client> *) const {
const definition<client> &_this = *this;
return boost::pfr::get<N>(_this);
}
template <std::size_t N>
constexpr decltype(auto) get(specification::user_definition<client> *) {
definition<client> &_this = *this;
return boost::pfr::get<N>(_this);
}
template <std::size_t N>
constexpr decltype(auto) get(auto_definition<client> *) const {
const definition<client> &_this = *this;
return _this.template get<N>();
}
template <std::size_t N>
constexpr decltype(auto) get(auto_definition<client> *) {
definition<client> &_this = *this;
return _this.template get<N>();
}
public:
template <std::size_t N> constexpr decltype(auto) get() const {
constexpr definition<client> *swtch{nullptr};
return get<N>(swtch);
}
template <std::size_t N> constexpr decltype(auto) get() {
constexpr definition<client> *swtch{nullptr};
return get<N>(swtch);
}
// utility
public:
template <typename F> constexpr decltype(auto) self_apply(F &&f) {
return f(*this);
}
template <typename F> constexpr decltype(auto) self_apply(F &&f) const {
return f(*this);
}
};
} // namespace value
} // namespace compile_time
#define FIELD(x...) \
self_apply([](auto &&e) constexpr->decltype(auto) { \
using type = typename DECT(e)::client_t; \
return e.template get_by_offset<offsetof(type, x)>(); \
})