-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsttr_visitor.h
201 lines (172 loc) · 6.53 KB
/
sttr_visitor.h
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// sttr_visitor.h
//
#ifndef LZZ_sttr_visitor_h
#define LZZ_sttr_visitor_h
#include <type_traits>
#include <string>
#include "type_to_string.hpp"
#define STTR_VISITOR_HEADER
#define STTR_ADD_VISITOR(mVisitorType) if (v->getSignature() == mVisitorType::getSignatureStatic()) { mVisitorType * vv = (mVisitorType *) v; vv->visit(this); return; }
#define STTR_ADD_CLASS_VISITOR(mVisitorType) if (v->getSignature() == mVisitorType::getSignatureStatic()) { mVisitorType * vv = (mVisitorType *) v; vv->visitClass(this); return; }
namespace sttr {
class NullType {};
template<typename ... Types> struct ParameterPack {};
template<typename T, typename CT, unsigned int FLAGS>
class Reg;
// Utility templates
// Yanks out the type of a member pointer
template <class CT, typename T, const size_t SZ> T* getTypePointingTo(T (CT::*v)[SZ]);
template <class CT, typename T> T getTypePointingTo(T CT::*v);
template <typename T> T getTypePointingTo(T * v);
template <typename T> T getTypePointingTo(T v);
// remove_member_pointer
// See: https://stackoverflow.com/questions/22213523/c11-14-how-to-remove-a-pointer-to-member-from-a-type
template<typename T, typename>
struct remove_member_pointer_helper { typedef T type; };
template<typename T, typename U, typename C>
struct remove_member_pointer_helper<T, U C::*> { typedef U type; };
template<typename T, typename U, typename C, const size_t SZ>
struct remove_member_pointer_helper<T, U (C::*)[SZ]> { typedef U type[SZ]; };
template<typename T>
struct remove_member_pointer
: public remove_member_pointer_helper<T, typename std::remove_cv<T>::type> {};
// template<class CT, typename T>
// inline T getBaseType(T *v) {}
// Disjunction - for versions of c++ older than std::c++17
template<class...> struct disjunction : std::false_type { };
template<class B1> struct disjunction<B1> : B1 { };
template<class B1, class... Bn>
struct disjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> { };
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
template <typename T>
using negate = std::integral_constant<bool, !T::value>;
template <typename T>
using is_function = sttr::disjunction<std::is_function<typename std::remove_pointer<T>::type>, std::is_member_function_pointer<T>>;
template <typename T>
using is_variable = sttr::negate<sttr::is_function<T>>;
template <typename T>
using is_static = sttr::negate<std::is_member_pointer<T>>;
template <typename T>
using is_const = std::is_const<typename std::remove_pointer<T>::type>;
template <typename T>
using is_default_constructible_non_const = sttr::conjunction<std::is_default_constructible<T>, sttr::negate<std::is_const<T>>>;
// template<typename T>
//static char * getTypeSignature(); // Should this be static??
inline std::string getTypeName_filterTypeOut(const std::string & in) {
// Find "with T = " and stop when reaching ";"
size_t start = in.find("T = ");
if (start == std::string::npos) return (in);
const std::string r = in.substr(start+4);
size_t end = r.find(";");
return (r.substr(0,end));
}
/// Prints the type of a function
#if __cplusplus >= 201703L
template<typename T>
inline const char * getTypeName() {
// This is set at compile time
return sttr::type_to_string_impl::TypeName<T>();
}
#else
template<typename T>
std::string getTypeName() {
// has to compile getTypeName_filterTypeOut - will spit out of heaps of asm (179 instructions for an int)
#ifndef STTR_SUPPRESS_CXX17_WARNING
#warning sttr::getTypeName - using slow code path. Enable c++17 or later to solve. (define STTR_SUPPRESS_CXX17_WARNING to suppress warning)
#endif
return sttr::getTypeName_filterTypeOut(__PRETTY_FUNCTION__).c_str();
}
#endif
}
#define LZZ_INLINE inline
namespace sttr {
template <typename T>
T * constructIfDefaultConstructible_worker (std::false_type isDefaultConstructible);
}
namespace sttr {
template <typename T>
T * constructIfDefaultConstructible_worker (std::true_type isDefaultConstructible);
}
namespace sttr {
template <typename T>
T * constructIfDefaultConstructible ();
}
namespace sttr {
template <typename T>
char * getTypeSignature ();
}
namespace sttr {
template <typename T, typename R>
bool isType (R const & r);
}
namespace sttr {
template <typename T, typename R>
bool isType (R const * const r);
}
namespace sttr {
template <typename T, typename R>
bool isType (R * const r);
}
namespace sttr {
class Visitor_Base {
public:
template <typename T, typename CT, unsigned int FLAGS = 0, typename CALLE = sttr::NullType>
void visit (sttr::Reg <T, CT, FLAGS> * RB, CALLE * cc = NULL);
template <typename T, typename CT, unsigned int FLAGS = 0>
void visitClass (sttr::Reg <T, CT, FLAGS> * CLASS);
virtual void * getSignature ();
static void * getSignatureStatic ();
};
}
namespace sttr {
template <typename T>
T * constructIfDefaultConstructible_worker (std::false_type isDefaultConstructible) { return NULL; }
}
namespace sttr {
template <typename T>
T * constructIfDefaultConstructible_worker (std::true_type isDefaultConstructible) { return new T; }
}
namespace sttr {
template <typename T>
T * constructIfDefaultConstructible () {
return constructIfDefaultConstructible_worker<T>(sttr::is_default_constructible_non_const<T>());
}
}
namespace sttr {
template <typename T>
char * getTypeSignature () {
static char R = 0;
return &R;
}
}
namespace sttr {
template <typename T, typename R>
LZZ_INLINE bool isType (R const & r) { return r.sttr_getClassSig() == (void*) sttr::getTypeSignature<T>(); }
}
namespace sttr {
template <typename T, typename R>
LZZ_INLINE bool isType (R const * const r) { return r->sttr_getClassSig() == (void*) sttr::getTypeSignature<T>(); }
}
namespace sttr {
template <typename T, typename R>
LZZ_INLINE bool isType (R * const r) { return r->sttr_getClassSig() == (void*) sttr::getTypeSignature<T>(); }
}
namespace sttr {
template <typename T, typename CT, unsigned int FLAGS, typename CALLE>
void Visitor_Base::visit (sttr::Reg <T, CT, FLAGS> * RB, CALLE * cc) {
// Your code here if deriving from this class
}
}
namespace sttr {
template <typename T, typename CT, unsigned int FLAGS>
void Visitor_Base::visitClass (sttr::Reg <T, CT, FLAGS> * CLASS) {
// This is called for RegNamespace::thisClass. Used to visit class types themselves
}
}
#undef LZZ_INLINE
#endif