├── .gitignore
├── LICENSE
├── README.md
├── any.hpp
├── declare.hpp
├── has_class.hpp
├── is_empty_tuple.hpp
├── main.cpp
├── member_function.hpp
├── member_variable.hpp
├── object.hpp
├── reflection.hpp
├── reflection.pro
├── reflection_base.hpp
├── static_function.hpp
├── static_variable.hpp
├── string_to_tag.hpp
└── test.hpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Compiled Dynamic libraries
8 | *.so
9 | *.dylib
10 | *.dll
11 |
12 | # Compiled Static libraries
13 | *.lai
14 | *.la
15 | *.a
16 | *.lib
17 |
18 | # Executables
19 | *.exe
20 | *.out
21 | *.app
22 | *.pro.user
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Reflection
2 | ==========
3 | This is a C++ reflection library which strive to provide the following feature:
4 |
5 | Compile time Inspection of existence/return type of type/variable/function
6 |
7 | Dynamical modification of second class citizen member function/ member
8 |
9 | Runtime Inspection of existence/return type of type/variable/function ( including second class citizen as well )
10 |
11 | Runtime calling of function/ extraction of variable ( also including second class citizen )
12 |
13 | while maintaining a minimal extra code ( only one line for the *entire program ) and no external tool dependency ( this is written with MetaProgramming ) directly
14 |
15 | You need MarisaKirisame/cpp_common to run it.
16 |
--------------------------------------------------------------------------------
/any.hpp:
--------------------------------------------------------------------------------
1 | #ifndef ANY_HPP
2 | #define ANY_HPP
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "member_variable.hpp"
8 | #include "static_variable.hpp"
9 | #include "member_function.hpp"
10 | #include "string_to_tag.hpp"
11 | #include "reflection_base.hpp"
12 | #include
13 | #define DECLARE_ANY( NAME, NAME_SEQ ) \
14 | struct NAME : reflection_base< NAME > \
15 | { \
16 | using reflection_base::has_member_variable; \
17 | using reflection_base::has_static_variable; \
18 | using reflection_base::has_static_function; \
19 | using reflection_base::has_member_function; \
20 | using reflection_base::get_member_variable; \
21 | using reflection_base::get_static_variable; \
22 | using reflection_base::call_static_function; \
23 | using reflection_base::static_variable_type; \
24 | using reflection_base::static_function_return_type; \
25 | using reflection_base::member_function_return_type; \
26 | using reflection_base::call_member_function; \
27 | using reflection_base::member_variable_type; \
28 | std::string any_typename; \
29 | template< typename T > \
30 | NAME( const T & t ) : \
31 | any_typename( tag< T >::name( ) ), \
32 | any_data( new any_internal_implement< typename std::remove_reference< T >::type >( t ) ), \
33 | copy_data( []( any_internal * ai ) \
34 | { \
35 | typename std::remove_reference< T >::type \
36 | t( * static_cast< typename std::remove_reference< T >::type * >( ai->data ) ); \
37 | return new any_internal_implement< typename std::remove_reference< T >::type >( t ); \
38 | } ) \
39 | { \
40 | if ( any_typename.empty( ) ) \
41 | { \
42 | delete static_cast< typename std::remove_reference< T >::type * >( any_data->data ); \
43 | throw unable_to_determine_type( ); \
44 | } \
45 | } \
46 | template< typename T > \
47 | NAME( T && t ) : \
48 | any_typename( tag< typename std::remove_reference< T >::type >::name( ) ),\
49 | any_data( new any_internal_implement< typename std::remove_reference< T >::type >( t ) ), \
50 | copy_data( []( any_internal * ai ) \
51 | { \
52 | typename std::remove_reference< T >::type t( \
53 | * static_cast< typename std::remove_reference< T >::type * >( ai->data ) ); \
54 | return new any_internal_implement< typename std::remove_reference< T >::type >( t ); \
55 | } ) \
56 | { \
57 | if ( any_typename.empty( ) ) \
58 | { \
59 | delete static_cast< typename std::remove_reference< T >::type * >( any_data->data ); \
60 | throw unable_to_determine_type( ); \
61 | } \
62 | } \
63 | struct any_internal \
64 | { \
65 | void * data; \
66 | virtual ~any_internal( ) { } \
67 | any_internal( void * d ) : data( d ) { } \
68 | }; \
69 | template< typename T > \
70 | struct any_internal_implement : any_internal \
71 | { \
72 | any_internal_implement( const T & t ) : any_internal( new T( t ) ) { } \
73 | any_internal_implement( T && t ) : any_internal( new T( std::move< T >( t ) ) ) { } \
74 | ~any_internal_implement( ) \
75 | { delete static_cast< T * >( data ); } \
76 | }; \
77 | any_internal * any_data; \
78 | std::function< any_internal * ( any_internal * ) > copy_data; \
79 | NAME( const NAME & n ) : \
80 | any_typename( n.any_typename ), any_data( n.copy_data( n.any_data ) ), copy_data( n.copy_data ) { } \
81 | NAME( NAME && n ) : \
82 | any_typename( std::move( n.any_typename ) ), \
83 | any_data( n.copy_data( n.any_data ) ), \
84 | copy_data( std::move( n.copy_data ) ) { } \
85 | NAME & operator =( const NAME & n ) \
86 | { \
87 | any_typename = n.any_typename; \
88 | any_data = n.copy_data( n.any_data ); \
89 | copy_data = n.copy_data; \
90 | return * this; \
91 | } \
92 | ~NAME( ) { delete any_data; } \
93 | template< typename TAG, typename CPS > \
94 | struct get_member_variable_helper \
95 | { \
96 | const CPS & k; \
97 | const NAME * that; \
98 | template< typename T > \
99 | void operator ( )( const tag< T > & ) const \
100 | { k( member_variable< T, TAG >( )( static_cast< T * >( that->any_data->data ) ) ); } \
101 | get_member_variable_helper( const NAME * that, const CPS & k ) : k( k ), that( that ) { } \
102 | }; \
103 | template< typename TAG, typename CPS > \
104 | void get_member_variable( const CPS & k ) \
105 | { string_to_tag( any_typename, get_member_variable_helper< TAG, CPS >( this, k ) ); } \
106 | template< typename TAG > \
107 | struct has_member_variable_helper \
108 | { \
109 | bool & store_to; \
110 | template< typename T > \
111 | void operator ( )( const tag< T > & ) const \
112 | { store_to = ::has_member_variable< T, TAG >::value; } \
113 | has_member_variable_helper( bool & store_to ) : store_to( store_to ) { } \
114 | }; \
115 | template< typename TAG > \
116 | bool has_member_variable( ) const \
117 | { \
118 | bool ret; \
119 | string_to_tag( any_typename, has_member_variable_helper< TAG >( ret ) ); \
120 | return ret; \
121 | } \
122 | template< typename TAG > \
123 | struct has_static_variable_helper \
124 | { \
125 | bool & store_to; \
126 | template< typename T > \
127 | void operator ( )( const tag< T > & ) const \
128 | { store_to = ::has_static_variable< T, TAG >::value; } \
129 | has_static_variable_helper( bool & store_to ) : store_to( store_to ) { } \
130 | }; \
131 | template< typename TAG > \
132 | bool has_static_variable( ) const \
133 | { \
134 | bool ret; \
135 | string_to_tag( any_typename, has_static_variable_helper< TAG >( ret ) ); \
136 | return ret; \
137 | } \
138 | template< typename TAG, typename CPS > \
139 | struct get_static_variable_helper \
140 | { \
141 | const CPS & k; \
142 | template< typename T > \
143 | void operator ( )( const tag< T > & ) const \
144 | { k( static_variable< T, TAG >( )( ) ); } \
145 | get_static_variable_helper( const CPS & k ) : k( k ) { } \
146 | }; \
147 | template< typename TAG, typename CPS > \
148 | void get_static_variable( const CPS & k ) const \
149 | { string_to_tag( any_typename, get_static_variable_helper< TAG, CPS >( k ) ); } \
150 | template< typename TAG, typename ... ARG > \
151 | void call_member_function( const ARG & ... r ) \
152 | { call_member_function_loop< TAG >( r ..., loop_tag( ) ); } \
153 | template< typename TAG, typename T, typename ... ARG > \
154 | void call_member_function_loop( const T & t, const ARG & ... r ) \
155 | { call_member_function_loop< TAG >( r ..., t ); } \
156 | template< typename TAG, typename T, typename ... ARG > \
157 | void call_member_function_loop( const T & t, loop_tag, const ARG & ... r ) \
158 | { call_member_function_inner< TAG >( t, r ... ); } \
159 | template< typename TAG, typename K, typename ... ARG > \
160 | void call_member_function_inner( const K & k, const ARG & ... arg ) \
161 | { string_to_tag( any_typename, call_member_function_delegate< TAG, K, ARG ... >( this, k, arg ... ) ); } \
162 | template< typename TTAG, typename KK, typename ... AARG > \
163 | struct call_member_function_delegate \
164 | { \
165 | struct inner \
166 | { \
167 | template< typename T, typename TAG, typename K, typename ... ARG > \
168 | static void function( \
169 | typename std::enable_if\
170 | < \
171 | std::is_same \
172 | < \
173 | typename ::member_function_return_type< T, TAG, ARG ... >::type, \
174 | void \
175 | >::value && \
176 | ::has_member_function< T, TAG, ARG ... >::value,\
177 | T * \
178 | >::type t, \
179 | const K & k, \
180 | const ARG & ... arg ) \
181 | { \
182 | ::call_member_function< T, TAG, ARG ... >( )( * t, arg ... );\
183 | k( ); \
184 | } \
185 | template< typename T, typename TAG, typename K, typename ... ARG > \
186 | static void function( \
187 | typename std::enable_if \
188 | < \
189 | ! std::is_same \
190 | < \
191 | typename ::member_function_return_type< T, TAG, ARG ... >::type,\
192 | void \
193 | >::value && \
194 | ::has_member_function< T, TAG, ARG ... >::value, \
195 | T * \
196 | >::type t, \
197 | const K & k, \
198 | const ARG & ... arg ) { k( ::call_member_function< T, TAG, ARG ... >( )( * t, arg ... ) ); } \
199 | template< typename T, typename TAG, typename K, typename ... ARG > \
200 | static void function( void *, const K & k, ... ) { k( no_existence( ) ); } \
201 | }; \
202 | NAME * that; \
203 | const KK & k; \
204 | std::tuple< typename std::add_pointer< const AARG >::type ... > data; \
205 | call_member_function_delegate( NAME * that, const KK & k, const AARG & ... a ) : \
206 | that( that ), k( k ), data( std::addressof( a ) ... ) { } \
207 | template< int i, typename T, typename ... ARG > \
208 | typename std::enable_if< i == std::tuple_size< decltype( data ) >::value >::type \
209 | func( const ARG & ... a ) const \
210 | { \
211 | inner::template function \
212 | < \
213 | T, \
214 | TTAG, \
215 | KK, \
216 | AARG ... \
217 | >( static_cast< T * >( that->any_data->data ), k, a ... ); \
218 | } \
219 | template< int i, typename T, typename ... ARG > \
220 | typename std::enable_if< i != std::tuple_size< decltype( data ) >::value >::type \
221 | func( const ARG & ... a ) const { func< i + 1, T >( a ..., * std::get< i >( data ) ); } \
222 | template< typename T > \
223 | void operator( )( const tag< T > & ) const \
224 | { func< 0, T >( ); } \
225 | }; \
226 | template< typename TAG, typename ... ARG > \
227 | void call_static_function( const ARG & ... r ) const \
228 | { call_static_function_loop< TAG >( r ..., loop_tag( ) ); } \
229 | template< typename TAG, typename T, typename ... ARG > \
230 | void call_static_function_loop( const T & t, const ARG & ... r ) const \
231 | { call_static_function_loop< TAG >( r ..., t ); } \
232 | template< typename TAG, typename T, typename ... ARG > \
233 | void call_static_function_loop( const T & t, loop_tag, const ARG & ... r ) const \
234 | { call_static_function_inner< TAG >( t, r ... ); } \
235 | template< typename TAG, typename K, typename ... ARG > \
236 | void call_static_function_inner( const K & k, const ARG & ... arg ) const \
237 | { string_to_tag( any_typename, call_static_function_delegate< TAG, K, ARG ... >( k, arg ... ) ); } \
238 | template< typename TTAG, typename KK, typename ... AARG > \
239 | struct call_static_function_delegate \
240 | { \
241 | struct inner \
242 | { \
243 | template< typename T, typename TAG, typename K, typename ... ARG > \
244 | static void function( \
245 | typename std::enable_if\
246 | < \
247 | std::is_same \
248 | < \
249 | typename ::static_function_return_type< T, TAG, ARG ... >::type, \
250 | void \
251 | >::value && \
252 | ::has_member_function< T, TAG, ARG ... >::value,\
253 | const K & \
254 | >::type k, \
255 | const ARG & ... arg ) \
256 | { \
257 | ::call_static_function< T, TAG, ARG ... >( )( arg ... );\
258 | k( ); \
259 | } \
260 | template< typename T, typename TAG, typename K, typename ... ARG > \
261 | static void function( \
262 | typename std::enable_if \
263 | < \
264 | ! std::is_same \
265 | < \
266 | typename ::static_function_return_type< T, TAG, ARG ... >::type, \
267 | void \
268 | >::value && \
269 | ::has_static_function< T, TAG, ARG ... >::value, \
270 | const K & \
271 | >::type k, \
272 | const ARG & ... arg ) { k( ::call_static_function< T, TAG, ARG ... >( )( arg ... ) ); } \
273 | template< typename T, typename TAG, typename K, typename ... ARG > \
274 | static void function( const K & k, ... ) { k( no_existence( ) ); } \
275 | }; \
276 | const KK & k; \
277 | std::tuple< typename std::add_pointer< const AARG >::type ... > data; \
278 | template< int i, typename T, typename ... ARG > \
279 | typename std::enable_if< i == std::tuple_size< decltype( data ) >::value >::type \
280 | func( const ARG & ... a ) const { inner::template function< T, TTAG, KK, AARG ... >( k, a ... ); } \
281 | template< int i, typename T, typename ... ARG > \
282 | typename std::enable_if< i != std::tuple_size< decltype( data ) >::value >::type \
283 | func( const ARG & ... a ) const { func< i + 1, T >( a ..., * std::get< i >( data ) ); } \
284 | template< typename T > \
285 | void operator( )( const tag< T > & ) const \
286 | { func< 0, T >( ); } \
287 | call_static_function_delegate( const KK & k, const AARG & ... a ) : \
288 | k( k ), data( std::addressof( a ) ... ) { } \
289 | }; \
290 | template< typename TAG, typename ... ARG > \
291 | struct has_static_function_helper \
292 | { \
293 | bool & store_to; \
294 | template< typename T > \
295 | void operator ( )( const tag< T > & ) const \
296 | { store_to = ::has_static_function< T, TAG, ARG ... >::value; } \
297 | has_static_function_helper( bool & store_to ) : store_to( store_to ) { } \
298 | }; \
299 | template< typename TAG, typename ... ARG > \
300 | bool has_static_function( ) const \
301 | { \
302 | bool ret; \
303 | string_to_tag( any_typename, has_static_function_helper< TAG, ARG ... >( ret ) ); \
304 | return ret; \
305 | } \
306 | template< typename TAG, typename ... ARG > \
307 | struct has_member_function_helper \
308 | { \
309 | bool & store_to; \
310 | template< typename T > \
311 | void operator ( )( const tag< T > & ) const \
312 | { store_to = ::has_member_function< T, TAG, ARG ... >::value; } \
313 | has_member_function_helper( bool & store_to ) : store_to( store_to ) { } \
314 | }; \
315 | template< typename TAG, typename ... ARG > \
316 | bool has_member_function( ) const \
317 | { \
318 | bool ret; \
319 | string_to_tag( any_typename, has_member_function_helper< TAG, ARG ... >( ret ) ); \
320 | return ret; \
321 | } \
322 | template< typename TAG, typename CPS > \
323 | struct member_variable_type_helper \
324 | { \
325 | const CPS & k; \
326 | template< typename T > \
327 | void operator ( )( const tag< T > & ) const \
328 | { k( tag< typename ::member_variable_type< T, TAG >::type >( ) ); } \
329 | member_variable_type_helper( const CPS & k ) : k( k ) { } \
330 | }; \
331 | template< typename TAG, typename K > \
332 | void member_variable_type( const K & k ) const \
333 | { string_to_tag( any_typename, member_variable_type_helper< TAG, K >( k ) ); } \
334 | template< typename TAG, typename CPS > \
335 | struct static_variable_type_helper \
336 | { \
337 | const CPS & k; \
338 | template< typename T > \
339 | void operator ( )( const tag< T > & ) const \
340 | { k( tag< typename ::static_variable_type< T, TAG >::type >( ) ); } \
341 | static_variable_type_helper( const CPS & k ) : k( k ) { } \
342 | }; \
343 | template< typename TAG, typename K > \
344 | void static_variable_type( const K & k ) const \
345 | { string_to_tag( any_typename, static_variable_type_helper< TAG, K >( k ) ); } \
346 | template< typename TAG, typename CPS, typename ... ARG > \
347 | struct static_function_return_type_helper \
348 | { \
349 | const CPS & k; \
350 | template< typename T > \
351 | void operator ( )( const tag< T > & ) const \
352 | { k( ::tag< typename ::static_function_return_type< T, TAG, ARG ... >::type >( ) ); } \
353 | static_function_return_type_helper( const CPS & k ) : k( k ) { } \
354 | }; \
355 | template< typename TAG, typename K, typename ... ARG > \
356 | void static_function_return_type_inner( const K & k ) const \
357 | { string_to_tag( any_typename, static_function_return_type_helper< TAG, K, ARG ... >( k ) ); } \
358 | template< typename TAG, typename CPS, typename ... ARG > \
359 | struct member_function_return_type_helper \
360 | { \
361 | const CPS & k; \
362 | template< typename T > \
363 | void operator ( )( const tag< T > & ) const \
364 | { k( ::tag< typename ::member_function_return_type< T, TAG, ARG ... >::type >( ) ); } \
365 | member_function_return_type_helper( const CPS & k ) : k( k ) { } \
366 | }; \
367 | template< typename TAG, typename K, typename ... ARG > \
368 | void member_function_return_type_inner( const K & k ) const \
369 | { string_to_tag( any_typename, member_function_return_type_helper< TAG, K, ARG ... >( k ) ); } \
370 | template< typename K > \
371 | struct type_restore_helper \
372 | { \
373 | const K & k; \
374 | const NAME * that; \
375 | type_restore_helper( const NAME * that, const K & k ) : k( k ), that( that ) { } \
376 | template< typename TAG > \
377 | typename std::enable_if< has_class< TAG >::value >::type \
378 | operator ( )( const tag< TAG > & ) const \
379 | { k( * static_cast< const TAG * >( that->any_data->data ) ); } \
380 | template< typename ... > \
381 | void operator ( )( ... ) const { k( no_existence( ) ); } \
382 | }; \
383 | template< typename K > \
384 | void type_restore( const K & k ) const \
385 | { string_to_tag( any_typename, type_restore_helper< K >( this, k ) ); } \
386 | };
387 | #endif // ANY_HPP
388 |
--------------------------------------------------------------------------------
/declare.hpp:
--------------------------------------------------------------------------------
1 | #ifndef DECLARE_HPP
2 | #define DECLARE_HPP
3 | #include
4 | #include
5 | #include
6 | #include "member_function.hpp"
7 | #include "static_function.hpp"
8 | #include "member_variable.hpp"
9 | #include "static_variable.hpp"
10 | #include "string_to_tag.hpp"
11 | template< typename >
12 | struct tag{ };
13 | #define DECLARE_NAME( R, DATA, NAME ) \
14 | struct NAME; \
15 | template< > \
16 | struct tag< NAME > \
17 | { \
18 | static constexpr const char * name( ) \
19 | { return BOOST_PP_STRINGIZE( NAME ); } \
20 | };
21 | #define DECLARE_NAMES( NAME_SEQ ) \
22 | BOOST_PP_SEQ_FOR_EACH( DECLARE_NAME, _, NAME_SEQ ) \
23 | DECLARE_STRING_TO_TAG( NAME_SEQ )
24 | #define DECLARE_TYPE( TYPE, NAME_SEQ ) \
25 | template< typename ... > \
26 | void invoke_member_variable( ... ) { } \
27 | template< typename K > \
28 | void invoke_all_member_variable( const K & k ) \
29 | { INVOKE_ALL_MEMBER_VARIABLE( k, NAME_SEQ ); } \
30 | DECLARE_ALL_POSSIBLE( NAME_SEQ )
31 | #define DECLARE_HELPER( TYPE, NAME_SEQ ) \
32 | template< > \
33 | struct helper< TYPE > \
34 | { \
35 | DECLARE_ALL_POSSIBLE_STATIC_VARIABLE( NAME_SEQ ) \
36 | DECLARE_ALL_POSSIBLE_MEMBER_VARIABLE( NAME_SEQ ) \
37 | DECLARE_ALL_POSSIBLE_STATIC_FUNCTION( NAME_SEQ ) \
38 | DECLARE_ALL_POSSIBLE_MEMBER_FUNCTION( NAME_SEQ ) \
39 | template< typename SELF, typename K > \
40 | static void \
41 | invoke_all_member_variable( SELF * t, const K & k ) \
42 | { INVOKE_ALL_MEMBER_VARIABLE( k, NAME_SEQ ) } \
43 | };
44 | #define DECLARE_ALL_HELPER( R, DATA, ELEMENT ) DECLARE_HELPER( ELEMENT, DATA )
45 | #define DECLARE_ALL( NAME_SEQ ) \
46 | BOOST_PP_LIST_FOR_EACH( DECLARE_ALL_HELPER, NAME_SEQ, BOOST_PP_SEQ_TO_LIST( NAME_SEQ ) )
47 | #endif //DECLARE_HPP
48 |
--------------------------------------------------------------------------------
/has_class.hpp:
--------------------------------------------------------------------------------
1 | #ifndef HAS_CLASS_HPP
2 | #define HAS_CLASS_HPP
3 | #include
4 | template< typename T >
5 | struct has_class
6 | {
7 | template< typename TT >
8 | static std::true_type function( decltype( std::declval< TT >( ).~TT( ) ) * );
9 | template< typename ... >
10 | static std::false_type function( ... );
11 | constexpr static bool value = decltype( function< T >( nullptr ) )::value;
12 | };
13 |
14 | #endif // HAS_CLASS_HPP
15 |
--------------------------------------------------------------------------------
/is_empty_tuple.hpp:
--------------------------------------------------------------------------------
1 | #ifndef IS_EMPTY_TUPLE_HPP
2 | #define IS_EMPTY_TUPLE_HPP
3 | #include
4 | #include
5 | #define HAS_COMMA_HELPER_HELPER(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
6 | #define HAS_COMMA_HELPER(...) HAS_COMMA_HELPER_HELPER(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
7 | #define EAT_PARENTHESIS(...) ,
8 | #define IS_EMPTY_TUPLE(...) IS_EMPTY_TUPLE_HELPER( BOOST_PP_TUPLE_ENUM( __VA_ARGS__ ) )
9 | #define IS_EMPTY_TUPLE_HELPER(...) \
10 | BOOST_PP_NOT( \
11 | BOOST_PP_OR( \
12 | BOOST_PP_OR( \
13 | BOOST_PP_OR( \
14 | HAS_COMMA_HELPER( __VA_ARGS__ ), \
15 | HAS_COMMA_HELPER( EAT_PARENTHESIS __VA_ARGS__ ) ), \
16 | HAS_COMMA_HELPER( __VA_ARGS__ ( ) ) ), \
17 | BOOST_PP_NOT( HAS_COMMA_HELPER( EAT_PARENTHESIS __VA_ARGS__ ( ) ) ) ) )
18 | #define LIMIT_IS_EMPTY_TUPLE 15
19 | #endif //IS_EMPTY_TUPLE_HPP
20 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
--------------------------------------------------------------------------------
/member_function.hpp:
--------------------------------------------------------------------------------
1 | #ifndef MEMBER_FUNCTION_HPP
2 | #define MEMBER_FUNCTION_HPP
3 | #include "reflection.hpp"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #define DECLARE_POSSIBLE_MEMBER_FUNCTION( NAME ) \
12 | template< typename SELF, typename TAG, typename ... ARG > \
13 | constexpr static bool has_member_function( \
14 | typename std::enable_if \
15 | < \
16 | std::is_same \
17 | < \
18 | TAG, \
19 | ::tag< NAME > \
20 | >::value && \
21 | ! ::has_static_function< SELF, TAG, ARG ... >::value, \
22 | typename std::add_pointer \
23 | < \
24 | decltype( std::declval< SELF * >( )->NAME( std::declval< ARG >( ) ... ) ) \
25 | >::type \
26 | >::type ) \
27 | { return true; } \
28 | template< typename SELF, typename T, typename ... R > \
29 | static typename std::enable_if \
30 | < \
31 | std::is_same \
32 | < \
33 | T, \
34 | ::tag< NAME > \
35 | >::value, \
36 | decltype( std::declval< SELF * >( )->NAME( std::declval< R >( ) ... ) ) \
37 | >::type \
38 | call_member_function( SELF & t, const R & ... r ) { return t.NAME( r ... ); } \
39 | template< typename SELF, typename T, typename ... R > \
40 | static typename std::enable_if \
41 | < \
42 | std::is_same \
43 | < \
44 | T, \
45 | ::tag< NAME > \
46 | >::value, \
47 | decltype( std::declval< SELF * >( )->NAME( std::declval< R >( ) ... ) ) \
48 | >::type \
49 | call_member_function( const SELF & t, const R & ... r ) { return t.NAME( r ... ); }
50 | template< typename TYPE, typename TTAG, typename ... AARG >
51 | struct has_member_function
52 | {
53 | template< typename, typename, typename ... >
54 | struct inner
55 | {
56 | template< typename TTYPE, typename TAG, typename ... ARG >
57 | static constexpr typename
58 | std::enable_if
59 | <
60 | helper< TTYPE >::template has_member_function< TTYPE, TAG, ARG ... >( nullptr ) || true,
61 | bool
62 | >::type function( typename std::enable_if< has_class< TTYPE >::value >::type * )
63 | { return helper< TTYPE >::template has_member_function< TTYPE, TAG, ARG ... >( nullptr ); }
64 | template< typename ... >
65 | static constexpr bool function( ... )
66 | { return false; }
67 | };
68 | template< typename T1, typename T2 >
69 | struct inner< T1, T2, void >
70 | {
71 | template< typename TTYPE, typename TAG, typename ... ARG >
72 | static constexpr typename
73 | std::enable_if
74 | <
75 | helper< TTYPE >::template has_member_function< TYPE, TAG >( nullptr ) || true,
76 | bool
77 | >::type function( typename std::enable_if< has_class< TTYPE >::value >::type * )
78 | { return helper< TTYPE >::template has_member_function< TYPE, TAG >( nullptr ); }
79 | template< typename ... >
80 | static constexpr bool function( ... )
81 | { return false; }
82 | };
83 | constexpr static bool value =
84 | inner< TYPE, TTAG, AARG ... >::template function< TYPE, TTAG, AARG ... >( nullptr );
85 | };
86 | template< typename TYPE, typename TAG, typename ... ARG >
87 | struct member_function_return_type
88 | {
89 | template< typename, typename, typename ... >
90 | struct member_function_return_type_inner
91 | {
92 | template< typename TTYPE, typename TTAG, typename ... AARG >
93 | static
94 | std::enable_if_t
95 | <
96 | has_member_function< TTYPE, TTAG, AARG ... >::value,
97 | decltype(
98 | helper< TTYPE >::template call_member_function< TTYPE, TTAG >(
99 | std::declval< TTYPE >( ),
100 | std::declval< AARG >( ) ... ) )
101 | >function( void * );
102 | template< typename ... >
103 | static no_existence function( ... );
104 | };
105 | template< typename T1, typename T2 >
106 | struct member_function_return_type_inner< T1, T2, void >
107 | {
108 | template< typename TTYPE, typename TTAG >
109 | static std::enable_if_t
110 | <
111 | has_member_function< TTYPE, TTAG >::value,
112 | decltype(
113 | helper< TTYPE >::template call_member_function< TYPE, TTAG >(
114 | std::declval< TTYPE >( ) ) )
115 | > function( );
116 | template< typename ... >
117 | static no_existence function( ... );
118 | };
119 | typedef decltype( member_function_return_type_inner< TYPE, TAG, ARG ... >::template
120 | function< TYPE, TAG, ARG ... >( nullptr ) ) type;
121 | };
122 | template< typename TYPE, typename TAG, typename ... ARG >
123 | struct call_member_function
124 | {
125 | decltype(
126 | helper< TYPE >::template call_member_function
127 | <
128 | TYPE,
129 | TAG
130 | >( std::declval
131 | <
132 | typename std::remove_reference< decltype( std::declval< TYPE >( ) ) >::type >( ),
133 | std::declval< ARG >( ) ... ) )
134 | operator ( )( TYPE & t, const ARG & ... r ) const
135 | { return helper< TYPE >::template call_member_function< TYPE, TAG, ARG ... >( t, r ... ); }
136 | decltype(
137 | helper< TYPE >::template call_member_function
138 | <
139 | TYPE,
140 | TAG
141 | >( std::declval
142 | <
143 | typename std::remove_reference< decltype( std::declval< TYPE >( ) ) >::type >( ),
144 | std::declval< ARG >( ) ... ) )
145 | operator ( )( const TYPE & t, const ARG & ... r ) const
146 | { return helper< TYPE >::template call_member_function< TYPE, TAG, ARG ... >( t, r ... ); }
147 | };
148 | template< typename TYPE, typename TAG >
149 | struct call_member_function< TYPE, TAG, void >
150 | {
151 | decltype( helper< TYPE >::template call_member_function< TYPE, TAG >( ) )
152 | operator ( )( const TYPE & t ) const
153 | { return helper< TYPE >::template call_member_function< TYPE, TAG >( t ); }
154 | decltype( helper< TYPE >::template call_member_function< TYPE, TAG >( ) )
155 | operator ( )( TYPE & t ) const
156 | { return helper< TYPE >::template call_member_function< TYPE, TAG >( t ); }
157 | };
158 | #define DECLARE_ALL_POSSIBLE_MEMBER_FUNCTION_HELPER( R, DATA, ELEMENT ) \
159 | DECLARE_POSSIBLE_MEMBER_FUNCTION( ELEMENT )
160 | #define DECLARE_ALL_POSSIBLE_MEMBER_FUNCTION( NAME_SEQ ) \
161 | BOOST_PP_SEQ_FOR_EACH( DECLARE_ALL_POSSIBLE_MEMBER_FUNCTION_HELPER, _, NAME_SEQ );
162 | #endif //MEMBER_FUNCTION_HPP
163 |
--------------------------------------------------------------------------------
/member_variable.hpp:
--------------------------------------------------------------------------------
1 | #ifndef MEMBER_VARIABLE_HPP
2 | #define MEMBER_VARIABLE_HPP
3 | #include "reflection.hpp"
4 | #include
5 | #define INVOKE_ALL_MEMBER_VARIABLE_HELPER( R, DATA, ELEMENT ) \
6 | invoke_member_variable \
7 | < \
8 | typename std::remove_reference< typename std::remove_cv< decltype( * t ) >::type >::type, \
9 | ::tag< ::ELEMENT >, \
10 | typename std::remove_cv< decltype( DATA ) >::type \
11 | >( t, DATA );
12 | #define INVOKE_ALL_MEMBER_VARIABLE( K, NAME_SEQ ) \
13 | BOOST_PP_SEQ_FOR_EACH( INVOKE_ALL_MEMBER_VARIABLE_HELPER, K, NAME_SEQ )
14 | #define DECLARE_POSSIBLE_MEMBER_VARIABLE( NAME, NAME_SEQ ) \
15 | template< typename SELF, typename TAG > \
16 | constexpr static bool has_member_variable( \
17 | typename std::enable_if \
18 | < \
19 | std::is_same \
20 | < \
21 | TAG, \
22 | ::tag< NAME > \
23 | >::value && \
24 | std::is_member_object_pointer< decltype( & SELF::NAME ) >::value, \
25 | decltype( std::declval< SELF * >( )->NAME ) \
26 | >::type * ) \
27 | { return true; } \
28 | template< typename SELF, typename TAG > \
29 | constexpr static typename \
30 | std::enable_if \
31 | < \
32 | std::is_same \
33 | < \
34 | TAG, \
35 | ::tag< ::NAME > \
36 | >::value, \
37 | bool \
38 | >::type has_member_variable( ... ) { return false; } \
39 | template< typename SELF, typename TAG > \
40 | static typename std::add_lvalue_reference \
41 | < \
42 | typename enable_if_valid \
43 | < \
44 | typename std::enable_if \
45 | < \
46 | std::is_same \
47 | < \
48 | TAG, \
49 | ::tag< NAME > \
50 | >::value \
51 | >::type, \
52 | decltype( std::declval< SELF * >( )->NAME ) \
53 | >::type \
54 | >::type get_member_variable( SELF * t ) { return t->NAME; } \
55 | template< typename SELF, typename TAG > \
56 | static typename enable_if_valid \
57 | < \
58 | typename std::enable_if \
59 | < \
60 | std::is_same \
61 | < \
62 | TAG, \
63 | ::tag< ::NAME > \
64 | >::value \
65 | >::type, \
66 | decltype( std::declval< SELF * >( )->NAME ) \
67 | >::type member_variable_type( ) { return static_cast< SELF * >( nullptr )->NAME; } \
68 | template< typename SELF, typename TAG, typename K > \
69 | static typename std::enable_if \
70 | < \
71 | std::is_same \
72 | < \
73 | TAG, \
74 | ::tag< ::NAME > \
75 | >::value && has_member_variable< SELF, TAG >( nullptr ), \
76 | typename enable_if_valid< decltype( std::declval< SELF * >( )->NAME ) >::type \
77 | >::type invoke_member_variable( SELF * t, const K & k ) \
78 | { \
79 | k( ::tag< ::NAME >( ), t->NAME ); \
80 | } \
81 | template< typename SELF, typename TAG, typename K > \
82 | static typename std::enable_if \
83 | < \
84 | std::is_same \
85 | < \
86 | TAG, \
87 | ::tag< ::NAME > \
88 | >::value \
89 | >::type invoke_member_variable( ... ) { }
90 | template< typename TYPE, typename TAG >
91 | struct has_member_variable
92 | {
93 | template< typename TTYPE, typename TTAG >
94 | constexpr static decltype( helper< TTYPE >::template has_member_variable< TTYPE, TTAG >( nullptr ) )
95 | function( void * )
96 | { return helper< TTYPE >::template has_member_variable< TTYPE, TTAG >( nullptr ); }
97 | template< typename ... >
98 | constexpr static bool function( ... ) { return false; }
99 | constexpr static bool value = function< TYPE, TAG >( nullptr );
100 | };
101 | template< typename TYPE, typename TAG >
102 | struct member_variable_type
103 | {
104 | template< typename TTYPE, typename TTAG >
105 | static
106 | std::enable_if_t
107 | <
108 | has_member_variable< TTYPE, TTAG >::value,
109 | decltype( helper< TTYPE >::template member_variable_type< TTYPE, TTAG >( ) )
110 | > function( void * );
111 | template< typename ... >
112 | static no_existence function( ... );
113 | typedef decltype( function< TYPE, TAG >( nullptr ) ) type;
114 | };
115 | template< typename TTYPE, typename NNAME >
116 | struct member_variable
117 | {
118 | template< typename TYPE, typename NAME >
119 | static decltype( helper< TYPE >::template get_member_variable< TYPE, NAME >( nullptr ) )
120 | function(
121 | typename std::enable_if
122 | <
123 | has_class< TYPE >::value &&
124 | has_member_variable< TYPE, NAME >::value,
125 | TYPE
126 | >::type * t )
127 | { return helper< TYPE >::template get_member_variable< TYPE, NAME >( t ); }
128 | template< typename TYPE, typename NAME >
129 | static no_existence function( ... ) { return no_existence( ); }
130 | decltype( function< TTYPE, NNAME >( std::declval< TTYPE * >( ) ) ) operator ( )( TTYPE * t )
131 | { return function< TTYPE, NNAME >( t ); }
132 | };
133 |
134 | template< typename T, typename K >
135 | void invoke_all_member_variable( T & t, const K & k )
136 | { helper< T >::template invoke_all_member_variable< T, K >( & t, k ); }
137 |
138 | #define DECLARE_ALL_POSSIBLE_MEMBER_VARIABLE_HELPER( R, DATA, ELEMENT ) \
139 | DECLARE_POSSIBLE_MEMBER_VARIABLE( ELEMENT, DATA )
140 | #define DECLARE_ALL_POSSIBLE_MEMBER_VARIABLE( NAME_SEQ ) \
141 | BOOST_PP_SEQ_FOR_EACH( DECLARE_ALL_POSSIBLE_MEMBER_VARIABLE_HELPER, NAME_SEQ, NAME_SEQ )
142 | #endif //MEMBER_VARIABLE_HPP
143 |
--------------------------------------------------------------------------------
/object.hpp:
--------------------------------------------------------------------------------
1 | #ifndef OBJECT_HPP
2 | #define OBJECT_HPP
3 | #include
4 | #include