Empirical
tuple_struct.h
Go to the documentation of this file.
1 // This file is part of Empirical, https://github.com/devosoft/Empirical
2 // Copyright (C) Michigan State University, 2015-2017.
3 // Released under the MIT Software license; see doc/LICENSE
4 //
5 
51 //
52 // Development notes:
53 // * Add static member function to help with reflection?
54 // * Make play nicely with serialization techniques.
55 // * It would be really awesome to make tuple structs (or at least the introspective ones)
56 // be indexable and iterable. (right now the main obstacle is type inference)
57 //
58 // Changes in last revision:
59 // * Changed name of macro that builds tuple that keeps track of variable names to
60 // EMP_BUILD_INTROSPECTIVE_TUPLE
61 // * Introspective tuples now also keep track of variable types and maintain an
62 // array of pointers to each element, which is very useful for doing operations on
63 // all memebrs of a tuple.
64 
65 #ifndef EMP_TUPLE_STRUCT_H
66 #define EMP_TUPLE_STRUCT_H
67 
68 #include <tuple>
69 #include <typeinfo>
70 #include <typeindex>
71 
72 #include "../base/macros.h"
73 
75 // For each entry, we want to build accessors to easily get and set each value.
76 #define EMP_BUILD_TUPLE_ACCESSORS(TUPLE_NAME, POS, TYPE, NAME) \
77  const TYPE & NAME() const { return std::get<POS>(TUPLE_NAME); } \
78  TYPE & NAME() { return std::get<POS>(TUPLE_NAME); } \
79  TYPE & NAME(const typename std::decay<TYPE>::type & _in) { \
80  std::get<POS>(TUPLE_NAME) = _in; \
81  return std::get<POS>(TUPLE_NAME); \
82  } \
83 
84 
85 // We have to figure out how many arguments we have.
86 // To get the last arg first (and know its position), reverse all arguments before sending them on.
87 #define EMP_BUILD_TUPLE_IMPL(TUPLE_NAME, ...) \
88  EMP_ASSEMBLE_MACRO_1ARG(EMP_BUILD_TUPLE_IMPL_, TUPLE_NAME, EMP_REVERSE_ARGS(__VA_ARGS__) )
89 
90 #define EMP_BUILD_TUPLE_IMPL_2(TNAME, NAME, TYPE) \
91  EMP_BUILD_TUPLE_ACCESSORS(TNAME, 0, TYPE, NAME)
92 #define EMP_BUILD_TUPLE_IMPL_4(TNAME, NAME, TYPE, ...) \
93  EMP_BUILD_TUPLE_IMPL_2(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 1, TYPE, NAME)
94 #define EMP_BUILD_TUPLE_IMPL_6(TNAME, NAME, TYPE, ...) \
95  EMP_BUILD_TUPLE_IMPL_4(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 2, TYPE, NAME)
96 #define EMP_BUILD_TUPLE_IMPL_8(TNAME, NAME, TYPE, ...) \
97  EMP_BUILD_TUPLE_IMPL_6(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 3, TYPE, NAME)
98 #define EMP_BUILD_TUPLE_IMPL_10(TNAME, NAME, TYPE, ...) \
99  EMP_BUILD_TUPLE_IMPL_8(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 4, TYPE, NAME)
100 #define EMP_BUILD_TUPLE_IMPL_12(TNAME, NAME, TYPE, ...) \
101  EMP_BUILD_TUPLE_IMPL_10(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 5, TYPE, NAME)
102 #define EMP_BUILD_TUPLE_IMPL_14(TNAME, NAME, TYPE, ...) \
103  EMP_BUILD_TUPLE_IMPL_12(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 6, TYPE, NAME)
104 #define EMP_BUILD_TUPLE_IMPL_16(TNAME, NAME, TYPE, ...) \
105  EMP_BUILD_TUPLE_IMPL_14(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 7, TYPE, NAME)
106 #define EMP_BUILD_TUPLE_IMPL_18(TNAME, NAME, TYPE, ...) \
107  EMP_BUILD_TUPLE_IMPL_16(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 8, TYPE, NAME)
108 #define EMP_BUILD_TUPLE_IMPL_20(TNAME, NAME, TYPE, ...) \
109  EMP_BUILD_TUPLE_IMPL_18(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 9, TYPE, NAME)
110 #define EMP_BUILD_TUPLE_IMPL_22(TNAME, NAME, TYPE, ...) \
111  EMP_BUILD_TUPLE_IMPL_20(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 10, TYPE, NAME)
112 #define EMP_BUILD_TUPLE_IMPL_24(TNAME, NAME, TYPE, ...) \
113  EMP_BUILD_TUPLE_IMPL_22(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 11, TYPE, NAME)
114 #define EMP_BUILD_TUPLE_IMPL_26(TNAME, NAME, TYPE, ...) \
115  EMP_BUILD_TUPLE_IMPL_24(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 12, TYPE, NAME)
116 #define EMP_BUILD_TUPLE_IMPL_28(TNAME, NAME, TYPE, ...) \
117  EMP_BUILD_TUPLE_IMPL_26(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 13, TYPE, NAME)
118 #define EMP_BUILD_TUPLE_IMPL_30(TNAME, NAME, TYPE, ...) \
119  EMP_BUILD_TUPLE_IMPL_28(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 14, TYPE, NAME)
120 #define EMP_BUILD_TUPLE_IMPL_32(TNAME, NAME, TYPE, ...) \
121  EMP_BUILD_TUPLE_IMPL_30(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 15, TYPE, NAME)
122 #define EMP_BUILD_TUPLE_IMPL_34(TNAME, NAME, TYPE, ...) \
123  EMP_BUILD_TUPLE_IMPL_32(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 16, TYPE, NAME)
124 #define EMP_BUILD_TUPLE_IMPL_36(TNAME, NAME, TYPE, ...) \
125  EMP_BUILD_TUPLE_IMPL_34(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 17, TYPE, NAME)
126 #define EMP_BUILD_TUPLE_IMPL_38(TNAME, NAME, TYPE, ...) \
127  EMP_BUILD_TUPLE_IMPL_36(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 18, TYPE, NAME)
128 #define EMP_BUILD_TUPLE_IMPL_40(TNAME, NAME, TYPE, ...) \
129  EMP_BUILD_TUPLE_IMPL_38(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 19, TYPE, NAME)
130 #define EMP_BUILD_TUPLE_IMPL_42(TNAME, NAME, TYPE, ...) \
131  EMP_BUILD_TUPLE_IMPL_40(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 20, TYPE, NAME)
132 #define EMP_BUILD_TUPLE_IMPL_44(TNAME, NAME, TYPE, ...) \
133  EMP_BUILD_TUPLE_IMPL_42(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 21, TYPE, NAME)
134 #define EMP_BUILD_TUPLE_IMPL_46(TNAME, NAME, TYPE, ...) \
135  EMP_BUILD_TUPLE_IMPL_44(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 22, TYPE, NAME)
136 #define EMP_BUILD_TUPLE_IMPL_48(TNAME, NAME, TYPE, ...) \
137  EMP_BUILD_TUPLE_IMPL_46(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 23, TYPE, NAME)
138 #define EMP_BUILD_TUPLE_IMPL_50(TNAME, NAME, TYPE, ...) \
139  EMP_BUILD_TUPLE_IMPL_48(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 24, TYPE, NAME)
140 #define EMP_BUILD_TUPLE_IMPL_52(TNAME, NAME, TYPE, ...) \
141  EMP_BUILD_TUPLE_IMPL_50(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 25, TYPE, NAME)
142 #define EMP_BUILD_TUPLE_IMPL_54(TNAME, NAME, TYPE, ...) \
143  EMP_BUILD_TUPLE_IMPL_52(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 26, TYPE, NAME)
144 #define EMP_BUILD_TUPLE_IMPL_56(TNAME, NAME, TYPE, ...) \
145  EMP_BUILD_TUPLE_IMPL_54(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 27, TYPE, NAME)
146 #define EMP_BUILD_TUPLE_IMPL_58(TNAME, NAME, TYPE, ...) \
147  EMP_BUILD_TUPLE_IMPL_56(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 28, TYPE, NAME)
148 #define EMP_BUILD_TUPLE_IMPL_60(TNAME, NAME, TYPE, ...) \
149  EMP_BUILD_TUPLE_IMPL_58(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 29, TYPE, NAME)
150 #define EMP_BUILD_TUPLE_IMPL_62(TNAME, NAME, TYPE, ...) \
151  EMP_BUILD_TUPLE_IMPL_60(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 30, TYPE, NAME)
152 #define EMP_BUILD_TUPLE_IMPL_64(TNAME, NAME, TYPE, ...) \
153  EMP_BUILD_TUPLE_IMPL_62(TNAME, __VA_ARGS__) EMP_BUILD_TUPLE_ACCESSORS(TNAME, 31, TYPE, NAME)
154 
155 
156 // Some debug additions!
157 #define EMP_BUILD_TUPLE_IMPL_0(...) { static_assert(false, "No args in BUILD_TUPLE!"); }
158 #define EMP_BUILD_TUPLE_IMPL_1(...) { static_assert(false, "Odd number of args in BUILD_TUPLE!"); }
159 
161 
162 #define EMP_BUILD_NAMED_TUPLE(TUPLE_NAME, ...) \
163  std::tuple< EMP_GET_ODD_ARGS(__VA_ARGS__) > TUPLE_NAME; \
164  EMP_BUILD_TUPLE_IMPL(TUPLE_NAME, __VA_ARGS__)
165 
167 #define EMP_BUILD_TUPLE(...) EMP_BUILD_NAMED_TUPLE(emp__tuple_body, __VA_ARGS__)
168 
170 
171 //Helper macros for building introspective tuples
172 #define GET_TYPEID(t) typeid(t)
173 #define GET_POINTER(A) &A()
174 
176 
180 #define EMP_BUILD_INTROSPECTIVE_NAMED_TUPLE(TUPLE_NAME, ...) \
181  const static int n_fields = EMP_COUNT_ARGS(EMP_GET_ODD_ARGS(__VA_ARGS__)); \
182  std::tuple< EMP_GET_ODD_ARGS(__VA_ARGS__) > TUPLE_NAME; \
183  EMP_BUILD_TUPLE_IMPL(TUPLE_NAME, __VA_ARGS__); \
184  std::array<std::string, EMP_COUNT_ARGS(EMP_GET_EVEN_ARGS(__VA_ARGS__))> \
185  var_names{{EMP_GET_EVEN_ARGS(EMP_STRINGIFY_EACH(__VA_ARGS__))}}; \
186  std::array<std::type_index, EMP_COUNT_ARGS(EMP_GET_ODD_ARGS(__VA_ARGS__))> \
187  var_types{{EMP_WRAP_ARGS(GET_TYPEID, EMP_GET_ODD_ARGS(__VA_ARGS__))}}; \
188  std::array<void *, EMP_COUNT_ARGS(EMP_GET_EVEN_ARGS(__VA_ARGS__))> \
189  pointers{{EMP_WRAP_ARGS(GET_POINTER, EMP_GET_EVEN_ARGS(__VA_ARGS__))}};
190 
209 #define EMP_BUILD_INTROSPECTIVE_TUPLE(...) EMP_BUILD_INTROSPECTIVE_NAMED_TUPLE(emp__tuple_body, __VA_ARGS__)
210 
211 
212 
213 #endif