20 #ifndef __TPIE_REFLECT_H__
21 #define __TPIE_REFLECT_H__
23 #include <type_traits>
29 #define REFLECT_XSTR(s) REFLECT_STR(s)
30 #define REFLECT_STR(s) #s
32 #define REFLECT_BEGIN(name) \
33 template <typename R, typename ... T> \
34 bool reflect_impl(name *, R & r, T && ... v) { \
35 r.begin(REFLECT_XSTR(name));
37 #define REFLECT_VISIT(naXme) \
38 r.name(REFLECT_XSTR(naXme)); \
39 if (!r.apply(v . naXme ...)) return false;
41 #define REFLECT_VISIT_SUPER(naXme) \
42 r.name(REFLECT_XSTR(naXme)); \
43 if (!r.apply(static_cast<std::conditional_t<R::write, naXme &, const naXme &>>(v) ...)) return false;
45 #define REFLECT_END() \
50 template <
typename R,
typename T,
typename ... TT>
51 bool reflect(R & r, T && v, TT && ... vs);
57 template <
typename TT>
58 static char magic(TT *,
typename std::enable_if<TT::is_trivially_serializable>::type *_=0);
60 template <
typename TT>
61 static long magic(...);
63 static bool constexpr value=
64 (std::is_pod<T>::value ||
sizeof(magic<T>((T*)
nullptr))==
sizeof(
char)) && !std::is_pointer<T>::value;
71 template <
typename TT>
72 static char size_and_lookup_magic(TT *,
73 decltype(std::declval<TT>().size()) * a = 0,
74 std::decay_t<decltype(std::declval<TT>()[0])> * b = 0);
75 template <
typename TT>
76 static long size_and_lookup_magic(...);
78 template <
typename TT>
79 static char resize_magic(TT *,
80 decltype(std::declval<TT>().resize(0)) * a = 0);
81 template <
typename TT>
82 static long resize_magic(...);
84 template <
typename TT>
85 static char push_back_magic(TT *,
86 decltype(std::declval<TT &>().push_back(std::declval<std::decay_t<decltype(std::declval<TT>()[0])>>())) * a = 0);
87 template <
typename TT>
88 static long push_back_magic(...);
90 template <
typename TT>
91 static char data_magic(TT *,
92 decltype(std::declval<TT>().data()) * a = 0);
93 template <
typename TT>
94 static long data_magic(...);
96 template <
typename TT>
97 static char c_str_magic(TT *,
98 decltype(std::declval<TT>().c_str()) * a = 0);
99 template <
typename TT>
100 static long c_str_magic(...);
102 template <
typename TT>
103 static std::enable_if_t<is_trivially_serializable2<std::decay_t<decltype(std::declval<TT>()[0])>>::value,
char> tsv_magic(TT *) {};
105 template <
typename TT>
106 static long tsv_magic(...);
108 static constexpr
bool size_and_lookup =
sizeof(size_and_lookup_magic<T>((T*)
nullptr)) ==
sizeof(
char);
109 static constexpr
bool resize =
sizeof(resize_magic<T>((T*)
nullptr)) ==
sizeof(
char);
110 static constexpr
bool push_back =
sizeof(push_back_magic<T>((T*)
nullptr)) ==
sizeof(
char);
111 static constexpr
bool data =
sizeof(data_magic<T>((T*)
nullptr)) ==
sizeof(
char);
112 static constexpr
bool c_str =
sizeof(c_str_magic<T>((T*)
nullptr)) ==
sizeof(
char);
113 static constexpr
bool trivially_serializable_value =
sizeof(tsv_magic<T>((T*)
nullptr)) ==
sizeof(
char);
125 template <
typename D,
typename R,
typename ... T>
127 return reflect_impl((D*)
nullptr, r, v...);
130 template <
typename D,
typename R,
typename ... T>
131 bool reflect_dispatch(reflect_tag_direct, R & r, T && ... v) {
135 template <
typename D,
typename R,
typename T,
typename ... TT>
136 bool reflect_dispatch(reflect_tag_array_read, R & r, T && v, TT && ... vs) {
137 const auto d = v.size();
138 r.beginArray(d, vs.size()...);
139 for (
size_t i=0; i < d; ++i) {
140 if (!reflect(r, v[i], vs[i]...))
return false;
146 template <
typename D,
typename R,
typename T>
147 bool reflect_dispatch(reflect_tag_trivial_array_read, R & r, T && v) {
148 const auto d = v.size();
150 if (!r(v.data(), v.size()))
return false;
155 template <
typename D,
typename R,
typename T>
156 bool reflect_dispatch(reflect_tag_array_write, R & r, T && v) {
157 size_t d = r.beginArray();
159 for (
size_t i=0; i < d; ++i) {
160 if (!r.apply(v[i]))
return false;
166 template <
typename D,
typename R,
typename T>
167 bool reflect_dispatch(reflect_tag_trivial_array_write, R & r, T && v) {
168 size_t d = r.beginArray();
170 if (!r(&v[0], d))
return false;
175 template <
typename D,
typename R,
typename T>
176 bool reflect_dispatch(reflect_tag_push_back_array_write, R & r, T && v) {
181 template <
size_t C,
typename R,
typename T>
182 bool reflect_static_array_dispatch(std::true_type, R & r, T && v) {
183 r.beginStaticArray(C);
184 if (!r(&v[0], C))
return false;
189 template <
size_t C,
typename R,
typename T,
typename ... TT>
190 bool reflect_static_array_dispatch(std::false_type, R & r, T && v, TT && ... vv) {
191 r.beginStaticArray(C);
192 for (
size_t i=0; i < C; ++i)
193 if (!r.applyt(v[i], vv[i]...))
return false;
198 template <
bool direct,
bool trivial_array_read,
bool array_read,
bool trivial_array_write,
bool push_back_array_write,
bool array_write>
203 template <
bool trivial_array_read,
bool array_read,
bool trivial_array_write,
bool push_back_array_write,
bool array_write>
204 struct reflect_tag_compute<true, trivial_array_read, array_read, trivial_array_write, push_back_array_write, array_write> {
208 template <
bool array_read>
218 template <
bool push_back_array_write,
bool array_write>
223 template <
bool array_write>
235 template <
typename R,
typename T,
typename ... TT>
236 bool reflect(R & r, T && v, TT && ... vs) {
237 typedef std::decay_t<T> D;
239 constexpr
bool dc = std::is_default_constructible<D>::value;
240 constexpr
bool write = R::write;
241 typedef std::decay_t<T> D;
244 (R::string && S::size_and_lookup && S::c_str && S::data) ||
246 (R::arithmetic && std::is_arithmetic<D>::value),
248 R::trivialSerializable && S::size_and_lookup && S::data && !write && S::trivially_serializable_value,
250 S::size_and_lookup && !write,
252 R::trivialSerializable && S::size_and_lookup && S::resize && S::data && write && S::trivially_serializable_value && dc,
256 S::size_and_lookup && dc && S::resize && write
258 return reflect_dispatch<D>(tag(), r, v, vs...);
262 template <
typename R,
typename T, std::size_t C,
typename ... TT>
263 bool reflect(R & r, T(& v)[C], TT && ... vs) {
264 typedef std::conditional_t<is_trivially_serializable2<T>::value, std::true_type, std::false_type> tag;
265 return reflect_static_array_dispatch<C>(tag(), r, v, vs...);
269 template <
typename R,
typename T, std::size_t C,
typename ... TT>
270 bool reflect(R & r,
const std::array<T, C> & v, TT && ... vs) {
271 typedef std::conditional_t<is_trivially_serializable2<T>::value, std::true_type, std::false_type> tag;
272 return reflect_static_array_dispatch<C>(tag(), r, v, vs...);
276 template <
typename R,
typename T, std::size_t C,
typename ... TT>
277 bool reflect(R & r, std::array<T, C> & v, TT && ... vs) {
278 typedef std::conditional_t<is_trivially_serializable<T>::value, std::true_type, std::false_type> tag;
279 return reflect_static_array_dispatch<C>(tag(), r, v, vs...);
283 #endif //_TPIE_REFLECT_H__