├── .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 5 | #include 6 | #include "member_variable.hpp" 7 | #include "string_to_tag.hpp" 8 | template< typename ANY, typename CRTP > 9 | struct object_base : reflection_base< object_base< ANY, CRTP > > 10 | { 11 | struct loop_tag { }; 12 | struct any_function 13 | { 14 | ANY function; 15 | template< typename ... ARG > 16 | void operator ( )( const ARG & ... r ) const 17 | { function.call_member_function( r ... ); } 18 | }; 19 | using reflection_base< object_base< ANY, CRTP > >::member_variable_type; 20 | std::map< std::string, ANY > member_variable; 21 | static std::map< std::string, ANY > & static_variable( ) 22 | { 23 | static std::map< std::string, ANY > ret; 24 | return ret; 25 | } 26 | static std::map< std::string, any_function > & member_function( ) 27 | { 28 | static std::map< std::string, any_function > ret; 29 | return ret; 30 | } 31 | static std::map< std::string, any_function > & static_function( ) 32 | { 33 | static std::map< std::string, any_function > ret; 34 | return ret; 35 | } 36 | template< typename TAG > 37 | bool has_member_variable( ) const 38 | { 39 | return 40 | ::has_member_variable< CRTP, TAG >::value || 41 | ( member_variable.count( TAG::name( ) ) > 0 ); 42 | } 43 | template< typename TAG > 44 | bool has_static_variable( ) const 45 | { 46 | return 47 | ::has_static_variable< CRTP, TAG >::value || 48 | ( static_variable( ).count( TAG::name( ) ) > 0 ); 49 | } 50 | struct has_member_variable_helper 51 | { 52 | const CRTP * that; 53 | bool & ret; 54 | template< typename TAG > 55 | void operator ( )( const TAG & ) const { ret = that->template has_member_variable< TAG >( ); } 56 | has_member_variable_helper( const CRTP * that, bool & ret ) : that( that ), ret( ret ) { } 57 | }; 58 | struct has_static_variable_helper 59 | { 60 | const CRTP * that; 61 | bool & ret; 62 | template< typename TAG > 63 | void operator ( )( const TAG & ) const { ret = that->template has_static_variable< TAG >( ); } 64 | has_static_variable_helper( const CRTP * that, bool & ret ) : that( that ), ret( ret ) { } 65 | }; 66 | bool has_member_variable( const std::string & str ) const 67 | { 68 | if ( member_variable.count( str ) > 0 ) { return true; } 69 | try 70 | { 71 | bool ret; 72 | string_to_tag( str, has_member_variable_helper( static_cast< const CRTP * >( this ), ret ) ); 73 | return ret; 74 | } 75 | catch ( const unable_to_determine_type & ) 76 | { return false; } 77 | } 78 | bool has_static_variable( const std::string & str ) const 79 | { 80 | if ( static_variable( ).count( str ) > 0 ) { return true; } 81 | try 82 | { 83 | bool ret; 84 | string_to_tag( str, has_static_variable_helper( static_cast< const CRTP * >( this ), ret ) ); 85 | return ret; 86 | } 87 | catch ( const unable_to_determine_type & ) 88 | { return false; } } 89 | template< typename TAG, typename K > 90 | typename 91 | std::enable_if< ::has_member_variable< CRTP, TAG >::value >::type get_member_variable( const K & k ) 92 | { k( ::member_variable< CRTP, TAG >( )( static_cast< CRTP * >( this ) ) ); } 93 | template< typename TAG, typename K > 94 | typename 95 | std::enable_if< ::has_static_variable< CRTP, TAG >::value >::type get_static_variable( const K & k ) const 96 | { k( ::static_variable< CRTP, TAG >( )( ) ); } 97 | template< typename TAG, typename K > 98 | typename 99 | std::enable_if< ! ::has_member_variable< CRTP, TAG >::value >::type get_member_variable( const K & k ) 100 | { get_member_variable( TAG::name( ), k ); } 101 | template< typename K > 102 | void get_member_variable( const std::string & str, const K & k ) 103 | { 104 | auto i = member_variable.find( str ); 105 | if ( i == member_variable.end( ) ) { k( no_existence( ) ); } 106 | else { i->type_restore( k ); } 107 | } 108 | template< typename K > 109 | void get_static_variable( const std::string & str, const K & k ) const 110 | { 111 | auto i = static_variable( ).find( str ); 112 | if ( i == static_variable( ).end( ) ) { k( no_existence( ) ); } 113 | else { i->type_restore( k ); } 114 | } 115 | template< typename TAG, typename K > 116 | typename 117 | std::enable_if< ! ::has_static_variable< CRTP, TAG >::value >::type 118 | get_static_variable( const K & k ) const { get_static_variable( TAG::name( ), k ); } 119 | bool add_member_variable( const std::string & str, const ANY & any ) 120 | { return member_variable.insert( std::make_pair( str, any ) ).second; } 121 | static bool add_static_variable( const std::string & str, const ANY & any ) 122 | { return static_variable( ).insert( std::make_pair( str, any ) ).second; } 123 | virtual ~object_base( ) { } 124 | template< typename K > 125 | struct make_tag 126 | { 127 | const K & k; 128 | template< typename T > 129 | void operator( )( const T & ) const { k( tag< typename std::remove_reference< T >::type >( ) ); } 130 | make_tag( const K & k ) : k( k ) { } 131 | }; 132 | template< typename TAG, typename K > 133 | void member_variable_type( const K & k ) const 134 | { 135 | if ( ::has_member_variable< CRTP, TAG >::value ) 136 | { k( tag< typename ::member_variable_type< CRTP, TAG >::type >( ) ); } 137 | else 138 | { 139 | auto i = member_variable.find( TAG::name( ) ); 140 | if ( i == member_variable.end( ) ) 141 | { k( tag< no_existence >( ) ); } 142 | else { i->second.type_restore( make_tag< K >( k ) ); } 143 | } 144 | } 145 | template< typename TAG, typename K > 146 | void static_variable_type( const K & k ) const 147 | { 148 | if ( ::has_static_variable< CRTP, TAG >::value ) 149 | { k( tag< typename ::static_variable_type< CRTP, TAG >::type >( ) ); } 150 | else 151 | { 152 | auto i = static_variable( ).find( TAG::name( ) ); 153 | if ( i == static_variable( ).end( ) ) 154 | { k( tag< no_existence >( ) ); } 155 | else { i->second.type_restore( make_tag< K >( k ) ); } 156 | } 157 | } 158 | template< typename K > 159 | struct member_variable_type_helper 160 | { 161 | const K & k; 162 | const CRTP * that; 163 | member_variable_type_helper( const CRTP * that, const K & k ) : k( k ), that( that ) { } 164 | template< typename TAG > 165 | void operator ( )( const TAG & ) const 166 | { 167 | if ( ::has_member_variable< CRTP, TAG >::value ) 168 | { k( tag< typename ::member_variable_type< CRTP, TAG >::type >( ) ); } 169 | else 170 | { 171 | auto i = that->member_variable.find( TAG::name( ) ); 172 | if ( i == that->member_variable.end( ) ) 173 | { k( tag< no_existence >( ) ); } 174 | else { i->second.type_restore( make_tag< K >( k ) ); } 175 | } 176 | } 177 | }; 178 | template< typename K > 179 | struct static_variable_type_helper 180 | { 181 | const K & k; 182 | const CRTP * that; 183 | static_variable_type_helper( const CRTP * that, const K & k ) : k( k ), that( that ) { } 184 | template< typename TAG > 185 | void operator ( )( const TAG & ) const 186 | { 187 | if ( ::has_static_variable< CRTP, TAG >::value ) 188 | { k( tag< decltype( ::static_variable_type< CRTP, TAG >( )( ) ) >( ) ); } 189 | else 190 | { 191 | auto i = static_variable( ).find( TAG::name( ) ); 192 | if ( i == static_variable( ).end( ) ) 193 | { k( tag< no_existence >( ) ); } 194 | else { i->second.type_restore( make_tag< K >( k ) ); } 195 | } 196 | } 197 | }; 198 | template< typename K > 199 | void member_variable_type( const std::string & str, const K & k ) const 200 | { 201 | try 202 | { 203 | string_to_tag( 204 | str, 205 | member_variable_type_helper< K >( static_cast< const CRTP * >( this ), k ) ); 206 | } 207 | catch ( const unable_to_determine_type & ) 208 | { 209 | auto i = member_variable.find( str ); 210 | if ( i == member_variable.end( ) ) 211 | { k( tag< no_existence >( ) ); } 212 | else { i->second.type_restore( make_tag< K >( k ) ); } 213 | } 214 | } 215 | template< typename K > 216 | void static_variable_type( const std::string & str, const K & k ) const 217 | { 218 | try 219 | { string_to_tag( str, member_variable_type_helper< K >( static_cast< const CRTP * >( this ), k ) ); } 220 | catch ( const unable_to_determine_type & ) 221 | { 222 | auto i = static_variable( ).find( str ); 223 | if ( i == static_variable( ).end( ) ) 224 | { k( tag< no_existence >( ) ); } 225 | else { i->second.type_restore( make_tag< K >( k ) ); } 226 | } 227 | } 228 | }; 229 | template< typename ANY > 230 | struct object : object_base< ANY, object< ANY > > 231 | { 232 | 233 | }; 234 | #endif // OBJECT_HPP 235 | -------------------------------------------------------------------------------- /reflection.hpp: -------------------------------------------------------------------------------- 1 | #ifndef REFLECTION_HPP 2 | #define REFLECTION_HPP 3 | #include "is_empty_tuple.hpp" 4 | #include 5 | #define EXPAND_TUPLE_ARGUMENT_HELPER( R, DATA, ELEMENT ) , ELEMENT 6 | #define EAT_ARG( ... ) 7 | #define EXPAND_TUPLE_ARGUMENT( ARGUMENT_TUPLE ) \ 8 | BOOST_PP_IIF( \ 9 | IS_EMPTY_TUPLE( ARGUMENT_TUPLE ), \ 10 | EAT_ARG, \ 11 | BOOST_PP_SEQ_FOR_EACH )\ 12 | ( \ 13 | EXPAND_TUPLE_ARGUMENT_HELPER, \ 14 | _, \ 15 | BOOST_PP_TUPLE_TO_SEQ( ARGUMENT_TUPLE ) ) 16 | #define DECLTYPE_HELPER( D, DATA, ELEMENT ) decltype( ELEMENT ) 17 | template< typename T, typename RET = void > 18 | struct enable_if_valid { typedef RET type; }; 19 | struct no_existence{ }; 20 | template < typename > struct helper; 21 | #endif //REFLECTION_HPP 22 | -------------------------------------------------------------------------------- /reflection.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | QMAKE_CXXFLAGS += -std=c++1z 6 | SOURCES += main.cpp 7 | LIBS += -lboost_unit_test_framework 8 | OTHER_FILES += 9 | 10 | HEADERS += \ 11 | declare.hpp \ 12 | member_function.hpp \ 13 | member_variable.hpp \ 14 | reflection.hpp \ 15 | static_function.hpp \ 16 | static_variable.hpp \ 17 | any.hpp \ 18 | object.hpp \ 19 | has_class.hpp \ 20 | string_to_tag.hpp \ 21 | reflection_base.hpp \ 22 | test.hpp 23 | 24 | -------------------------------------------------------------------------------- /reflection_base.hpp: -------------------------------------------------------------------------------- 1 | #ifndef REFLECTION_BASE_HPP 2 | #define REFLECTION_BASE_HPP 3 | #include 4 | #include "static_variable.hpp" 5 | #include "member_variable.hpp" 6 | #include "static_function.hpp" 7 | #include "member_function.hpp" 8 | #include "string_to_tag.hpp" 9 | template< typename CRTP > 10 | struct reflection_base 11 | { 12 | template< typename TAG, typename CPS > 13 | struct static_variable_type_helper 14 | { 15 | const CPS & k; 16 | template< typename T > 17 | void operator ( )( const tag< T > & ) const 18 | { k( tag< typename ::static_variable_type< T, TAG >::type >( ) ); } 19 | static_variable_type_helper( const CPS & k ) : k( k ) { } 20 | }; 21 | template< typename TAG, typename K > 22 | void static_variable_type( const K & k ) const 23 | { k( tag< typename ::static_variable_type< CRTP, TAG >::type >( ) ); } 24 | template< typename TAG, typename CPS > 25 | struct member_variable_type_helper 26 | { 27 | const CPS & k; 28 | template< typename T > 29 | void operator ( )( const tag< T > & ) const 30 | { k( tag< typename ::member_variable_type< T, TAG >::type >( ) ); } 31 | member_variable_type_helper( const CPS & k ) : k( k ) { } 32 | }; 33 | template< typename TAG, typename K > 34 | void member_variable_type( const K & k ) const 35 | { k( tag< typename ::member_variable_type< CRTP, TAG >::type >( ) ); } 36 | struct has_member_variable_string_helper 37 | { 38 | bool & store_to; 39 | const CRTP * that; 40 | template< typename T > 41 | void operator ( )( const T & ) const 42 | { store_to = that->template has_member_variable< T >( ); } 43 | has_member_variable_string_helper( const CRTP * that, bool & store_to ) : 44 | store_to( store_to ), that( that ) { } 45 | }; 46 | bool has_member_variable( const std::string & str ) const 47 | { 48 | bool ret; 49 | string_to_tag( str, has_member_variable_string_helper( static_cast< const CRTP * >( this ), ret ) ); 50 | return ret; 51 | } 52 | struct has_static_variable_string_helper 53 | { 54 | bool & store_to; 55 | const CRTP * that; 56 | template< typename T > 57 | void operator ( )( const T & ) const 58 | { store_to = that->template has_static_variable< T >( ); } 59 | has_static_variable_string_helper( const CRTP * that, bool & store_to ) : 60 | store_to( store_to ), that( that ) { } 61 | }; 62 | bool has_static_variable( const std::string tag ) const 63 | { 64 | bool ret; 65 | string_to_tag( tag, has_static_variable_string_helper( static_cast< const CRTP * >( this ), ret ) ); 66 | return ret; 67 | } 68 | template< typename ... ARG > 69 | struct has_static_function_string_helper 70 | { 71 | bool & store_to; 72 | const CRTP * that; 73 | template< typename T > 74 | void operator ( )( const T & ) const 75 | { store_to = that->template has_static_function< T, ARG ... >( ); } 76 | has_static_function_string_helper( const CRTP * that, bool & store_to ) : 77 | store_to( store_to ), that( that ) { } 78 | }; 79 | template< typename ... ARG > 80 | bool has_static_function( const std::string & tag ) const 81 | { 82 | bool ret; 83 | string_to_tag( 84 | tag, 85 | has_static_function_string_helper< ARG ... >( static_cast< const CRTP * >( this ), ret ) ); 86 | return ret; 87 | } 88 | template< typename ... ARG > 89 | struct has_member_function_string_helper 90 | { 91 | bool & store_to; 92 | const CRTP * that; 93 | template< typename T > 94 | void operator ( )( const T & ) const 95 | { store_to = that->template has_member_function< T, ARG ... >( ); } 96 | has_member_function_string_helper( const CRTP * that, bool & store_to ) : 97 | store_to( store_to ), that( that ) { } 98 | }; 99 | template< typename CPS > 100 | struct get_static_variable_string_helper 101 | { 102 | const CPS & k; 103 | const CRTP * that; 104 | get_static_variable_string_helper( const CRTP * that, const CPS & k ) : k( k ), that( that ) { } 105 | template< typename TAG > 106 | void operator ( )( const TAG & ) const 107 | { that->template get_static_variable< TAG, CPS >( k ); } 108 | }; 109 | template< typename ... ARG > 110 | struct call_static_function_string_helper 111 | { 112 | const CRTP * that; 113 | std::tuple< typename std::add_pointer< const ARG >::type ... > data; 114 | call_static_function_string_helper( const CRTP * that, const ARG & ... a ) : 115 | that( that ), data( std::addressof( a ) ... ) { } 116 | template< typename TAG > 117 | void operator ( )( const TAG & ) const { func< 0, TAG >( ); } 118 | template< int i, typename T, typename ... AARG > 119 | typename std::enable_if< i == std::tuple_size< decltype( data ) >::value >::type 120 | func( const AARG & ... a ) const { that->template call_static_function< T, ARG ... >( a ... ); } 121 | template< int i, typename T, typename ... AARG > 122 | typename std::enable_if< i != std::tuple_size< decltype( data ) >::value >::type 123 | func( const AARG & ... a ) const { func< i + 1, T >( a ..., * std::get< i >( data ) ); } 124 | }; 125 | template< typename ... ARG > 126 | void call_static_function( const std::string & str, const ARG & ... r ) const 127 | { 128 | string_to_tag( 129 | str, 130 | call_static_function_string_helper< ARG ... >( static_cast< const CRTP * >( this ), r ... ) ); 131 | } 132 | template< typename CPS > 133 | void get_static_variable( const std::string & tag, const CPS & k ) const 134 | { 135 | string_to_tag( 136 | tag, 137 | get_static_variable_string_helper< CPS >( static_cast< const CRTP * >( this ), k ) ); 138 | } 139 | template< typename TAG, typename ... ARG > 140 | struct has_member_function_helper 141 | { 142 | bool & store_to; 143 | template< typename T > 144 | void operator ( )( const tag< T > & ) const 145 | { store_to = ::has_member_function< T, TAG, ARG ... >::value; } 146 | has_member_function_helper( bool & store_to ) : store_to( store_to ) { } 147 | }; 148 | template< typename ... ARG > 149 | bool has_member_function( const std::string & tag ) const 150 | { 151 | bool ret; 152 | string_to_tag( 153 | tag, 154 | has_member_function_string_helper< ARG ... >( static_cast< const CRTP * >( this ), ret ) ); 155 | return ret; 156 | } 157 | template< typename CPS > 158 | struct get_member_variable_string_helper 159 | { 160 | const CPS & k; 161 | CRTP * that; 162 | get_member_variable_string_helper( CRTP * that, const CPS & k ) : k( k ), that( that ) { } 163 | template< typename T > 164 | void operator ( )( const T & ) const { that->template get_member_variable< T, CPS >( k ); } 165 | }; 166 | template< typename CPS > 167 | void get_member_variable( const std::string & tag, const CPS & k ) 168 | { string_to_tag( tag, get_member_variable_string_helper< CPS >( static_cast< CRTP * >( this ), k ) ); } 169 | template< typename CPS > 170 | struct static_variable_type_string_helper 171 | { 172 | const CPS & k; 173 | const CRTP * that; 174 | static_variable_type_string_helper( const CRTP * that, const CPS & k ) : k( k ), that( that ) { } 175 | template< typename T > 176 | void operator ( )( const T & ) const { that->template static_variable_type< T, CPS >( k ); } 177 | }; 178 | template< typename K > 179 | void static_variable_type( const std::string & tag, const K & k ) const 180 | { 181 | string_to_tag( 182 | tag, 183 | static_variable_type_string_helper< K >( static_cast< const CRTP * >( this ), k ) ); 184 | } 185 | template< typename ... ARG > 186 | struct static_function_return_type_string_delegate 187 | { 188 | const CRTP * that; 189 | std::string tag; 190 | template< typename T > 191 | struct inner 192 | { 193 | const CRTP * that; 194 | const T & t; 195 | template< typename TAG > 196 | void operator( )( const TAG & ) const 197 | { that->template static_function_return_type< TAG, ARG ... >( )( t ); } 198 | inner( const CRTP * that, const T & t ) : that( that ), t( t ) { } 199 | }; 200 | template< typename T > 201 | void operator( )( const T & t ) const { string_to_tag( tag, inner< T >( that, t ) ); } 202 | static_function_return_type_string_delegate( const CRTP * that, const std::string & tag ) : 203 | that( that ), tag( tag ) { } 204 | }; 205 | template< typename ... ARG > 206 | static_function_return_type_string_delegate< ARG ... > 207 | static_function_return_type( const std::string & tag ) const 208 | { 209 | return static_function_return_type_string_delegate< ARG ... >( 210 | static_cast< const CRTP * >( this ), 211 | tag ); 212 | } 213 | template< typename ... ARG > 214 | struct member_function_return_type_string_delegate 215 | { 216 | const CRTP * that; 217 | std::string tag; 218 | template< typename K > 219 | struct inner 220 | { 221 | const CRTP * that; 222 | const K & t; 223 | template< typename TAG > 224 | void operator( )( const TAG & ) const 225 | { that->template member_function_return_type< TAG, ARG ... >( )( t ); } 226 | inner( const CRTP * that, const K & t ) : that( that ), t( t ) { } 227 | }; 228 | template< typename T > 229 | void operator( )( const T & t ) const { string_to_tag( tag, inner< T >( that, t ) ); } 230 | member_function_return_type_string_delegate( const CRTP * that, const std::string & tag ) : 231 | that( that ), tag( tag ) { } 232 | }; 233 | template< typename ... ARG > 234 | member_function_return_type_string_delegate< ARG ... > 235 | member_function_return_type( const std::string & tag ) const 236 | { 237 | return member_function_return_type_string_delegate< ARG ... >( 238 | static_cast< const CRTP * >( this ), 239 | tag ); 240 | } 241 | template< typename ... ARG > 242 | void call_member_function( const std::string & tag, const ARG & ... r ) 243 | { 244 | string_to_tag( 245 | tag, 246 | call_member_function_string_helper< ARG ... >( static_cast< CRTP * >( this ), r ... ) ); 247 | } 248 | template< typename ... ARG > 249 | struct call_member_function_string_helper 250 | { 251 | CRTP * that; 252 | std::tuple< typename std::add_pointer< const ARG >::type ... > data; 253 | call_member_function_string_helper( CRTP * that, const ARG & ... a ) : 254 | that( that ), data( std::addressof( a ) ... ) { } 255 | template< typename TAG > 256 | void operator ( )( const TAG & ) const { func< 0, TAG >( ); } 257 | template< int i, typename T, typename ... AARG > 258 | typename std::enable_if< i == std::tuple_size< decltype( data ) >::value >::type 259 | func( const AARG & ... a ) const { that->template call_member_function< T, ARG ... >( a ... ); } 260 | template< int i, typename T, typename ... AARG > 261 | typename std::enable_if< i != std::tuple_size< decltype( data ) >::value >::type 262 | func( const AARG & ... a ) const { func< i + 1, T >( a ..., * std::get< i >( data ) ); } 263 | }; 264 | template< typename CPS > 265 | struct member_variable_type_string_helper 266 | { 267 | const CPS & k; 268 | const CRTP * that; 269 | member_variable_type_string_helper( const CRTP * that, const CPS & k ) : k( k ), that( that ) { } 270 | template< typename T > 271 | void operator ( )( const T & ) const { that->template member_variable_type< T, CPS >( k ); } 272 | }; 273 | struct loop_tag{ }; 274 | template< typename K > 275 | void member_variable_type( const std::string & tag, const K & k ) const 276 | { 277 | string_to_tag( 278 | tag, 279 | member_variable_type_string_helper< K >( static_cast< const CRTP * >( this ), k ) ); 280 | } 281 | template< typename TAG, typename ... ARG > 282 | void call_member_function( const ARG & ... r ) 283 | { call_member_function_loop< TAG >( r ..., loop_tag( ) ); } 284 | template< typename TAG, typename T, typename ... ARG > 285 | void call_member_function_loop( const T & t, const ARG & ... r ) 286 | { call_member_function_loop< TAG >( r ..., t ); } 287 | template< typename TAG, typename T, typename ... ARG > 288 | void call_member_function_loop( const T & t, loop_tag, const ARG & ... r ) 289 | { call_member_function_inner< TAG >( t, r ... ); } 290 | template< typename TAG, typename K, typename ... ARG > 291 | typename 292 | std::enable_if 293 | < 294 | ! std::is_same< typename ::member_function_return_type< CRTP, TAG, ARG ... >::type , void >::value && 295 | ::has_member_function< CRTP, TAG, ARG ... >::value 296 | >::type call_member_function_inner( const K & k, const ARG & ... arg ) 297 | { k( ::call_member_function< CRTP, TAG, ARG ... >( )( * static_cast< CRTP * >( this ), arg ... ) ); } 298 | template< typename TAG, typename K, typename ... ARG > 299 | typename 300 | std::enable_if 301 | < 302 | std::is_same< typename ::member_function_return_type< CRTP, TAG, ARG ... >::type , void >::value && 303 | ::has_member_function< CRTP, TAG, ARG ... >::value 304 | >::type call_member_function_inner( const K & k, const ARG & ... arg ) 305 | { 306 | ::call_member_function< CRTP, TAG, ARG ... >( )( * static_cast< CRTP * >( this ), arg ... ); 307 | k( ); 308 | } 309 | template< typename TAG, typename ... ARG > 310 | void call_static_function( const ARG & ... r ) const 311 | { call_static_function_loop< TAG >( r ..., loop_tag( ) ); } 312 | template< typename TAG, typename T, typename ... ARG > 313 | void call_static_function_loop( const T & t, const ARG & ... r ) const 314 | { call_static_function_loop< TAG >( r ..., t ); } 315 | template< typename TAG, typename T, typename ... ARG > 316 | void call_static_function_loop( const T & t, loop_tag, const ARG & ... r ) const 317 | { call_static_function_inner< TAG >( t, r ... ); } 318 | template< typename TAG, typename K, typename ... ARG > 319 | typename std::enable_if 320 | < 321 | std::is_same< typename ::static_function_return_type< CRTP, TAG, ARG ... >::type, void >::value && 322 | ::has_static_function< CRTP, TAG, ARG ... >::value 323 | >::type call_static_function_inner( const K & k, const ARG & ... arg ) const 324 | { 325 | ::call_static_function< CRTP, TAG, ARG ... >( )( arg ... ); 326 | k( ); 327 | } 328 | template< typename TAG, typename K, typename ... ARG > 329 | typename std::enable_if 330 | < 331 | ! std::is_same< typename ::static_function_return_type< CRTP, TAG, ARG ... >::type, void >::value && 332 | ::has_static_function< CRTP, TAG, ARG ... >::value 333 | >::type call_static_function_inner( const K & k, const ARG & ... arg ) const 334 | { k( ::call_static_function< CRTP, TAG, ARG ... >( )( arg ... ) ); } 335 | template< typename TAG, typename K, typename ... ARG > 336 | typename std::enable_if< ! ::has_static_function< CRTP, TAG, ARG ... >::value >::type 337 | call_static_function_inner( const K & k, ... ) const 338 | { k( no_existence( ) ); } 339 | template< typename TAG, typename K, typename ... ARG > 340 | typename std::enable_if< ! ::has_member_function< CRTP, TAG, ARG ... >::value >::type 341 | call_member_function_inner( const K & k, ... ) const 342 | { k( no_existence( ) ); } 343 | template< typename TAG, typename ... ARG > 344 | struct member_function_return_type_delegate 345 | { 346 | const CRTP * that; 347 | template< typename K > 348 | void operator( )( const K & k ) const 349 | { that->template member_function_return_type_inner< TAG, K, ARG ... >( k ); } 350 | member_function_return_type_delegate( const CRTP * that ) : that( that ) { } 351 | }; 352 | template< typename TAG, typename ... ARG > 353 | member_function_return_type_delegate< TAG, ARG ... > member_function_return_type( ) const 354 | { return member_function_return_type_delegate< TAG, ARG ... >( static_cast< const CRTP * >( this ) ); } 355 | template< typename TAG, typename K, typename ... ARG > 356 | void member_function_return_type_inner( const K & k ) const 357 | { k( tag< typename ::member_function_return_type< CRTP, TAG, ARG ... >::type >( ) ); } 358 | template< typename TAG, typename K, typename ... ARG > 359 | void static_function_return_type_inner( const K & k ) const 360 | { k( tag< typename ::static_function_return_type< CRTP, TAG, ARG ... >::type >( ) ); } 361 | template< typename TAG, typename ... ARG > 362 | struct static_function_return_type_delegate 363 | { 364 | const CRTP * that; 365 | template< typename K > 366 | void operator( )( const K & k ) const 367 | { that->template static_function_return_type_inner< TAG, K, ARG ... >( k ); } 368 | static_function_return_type_delegate( const CRTP * that ) : that( that ) { } 369 | }; 370 | template< typename TAG, typename ... ARG > 371 | static_function_return_type_delegate< TAG, ARG ... > static_function_return_type( ) const 372 | { return static_function_return_type_delegate< TAG, ARG ... >( static_cast< const CRTP * >( this ) ); } 373 | virtual ~reflection_base( ) { } 374 | template< typename TAG, typename CPS > 375 | void get_member_variable( const CPS & k ) 376 | { k( ::member_variable< CRTP, TAG >( )( static_cast< CRTP * >( this ) ) ); } 377 | template< typename TAG, typename CPS > 378 | void get_static_variable( const CPS & k ) const 379 | { k( ::static_variable< CRTP, TAG >( )( ) ); } 380 | template< typename TAG > 381 | constexpr bool has_member_variable( ) const { return ::has_member_variable< CRTP, TAG >::value; } 382 | template< typename TAG > 383 | constexpr bool has_static_variable( ) const { return ::has_static_variable< CRTP, TAG >::value; } 384 | template< typename TAG, typename ... ARG > 385 | constexpr bool has_member_function( ) const { return ::has_member_function< CRTP, TAG, ARG ... >::value; } 386 | template< typename TAG, typename ... ARG > 387 | constexpr bool has_static_function( ) const { return ::has_static_function< CRTP, TAG, ARG ... >::value; } 388 | }; 389 | #endif // REFLECTION_BASE_HPP 390 | -------------------------------------------------------------------------------- /static_function.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STATIC_FUNCTION_HPP 2 | #define STATIC_FUNCTION_HPP 3 | #include "reflection.hpp" 4 | #include 5 | #define DECLARE_POSSIBLE_STATIC_FUNCTION( NAME ) \ 6 | template< typename SELF, typename T, typename ... R > \ 7 | constexpr static bool has_static_function( \ 8 | typename std::enable_if \ 9 | < \ 10 | std::is_same \ 11 | < \ 12 | T, \ 13 | ::tag< NAME > \ 14 | >::value, \ 15 | typename std::add_pointer \ 16 | < \ 17 | decltype( SELF::NAME( std::declval< R >( ) ... ) ) \ 18 | >::type \ 19 | >::type ) \ 20 | { return true; } \ 21 | template< typename SELF, typename T, typename ... R > \ 22 | typename std::enable_if \ 23 | < \ 24 | std::is_same \ 25 | < \ 26 | T, \ 27 | ::tag< ::NAME > \ 28 | >::value, \ 29 | decltype( SELF::NAME( std::declval< R >( ) ... ) ) \ 30 | >::type \ 31 | static call_static_function( const R & ... r ) { return SELF::NAME( r ... ); } 32 | template< typename TYPE, typename TAG, typename ... AARG > 33 | struct has_static_function 34 | { 35 | template< typename, typename, typename ... > 36 | struct inner 37 | { 38 | template< typename TTYPE, typename TTAG, typename ... ARG > 39 | static constexpr typename 40 | std::enable_if 41 | < 42 | helper< TTYPE >::template has_static_function< TTYPE, TTAG, ARG ... >( nullptr ) || true, 43 | bool 44 | >::type function( typename std::enable_if< has_class< TTYPE >::value >::type * ) 45 | { return helper< TTYPE >::template has_static_function< TTYPE, TAG, ARG ... >( nullptr ); } 46 | template< typename ... > 47 | static constexpr bool function( ... ) { return false; } 48 | }; 49 | template< typename T1, typename T2 > 50 | struct inner< T1, T2, void > 51 | { 52 | template< typename TTYPE, typename TTAG > 53 | static constexpr bool function( typename std::enable_if< has_class< TYPE >::value >::type * ) 54 | { return helper< TTYPE >::template has_static_function< TTYPE, TTAG >( nullptr ); } 55 | template< typename ... > 56 | static constexpr bool function( ... ) { return false; } 57 | }; 58 | constexpr static bool value = 59 | inner< TYPE, TAG, AARG ... >::template function< TYPE, TAG, AARG ... >( nullptr ); 60 | }; 61 | template< typename TTTYPE, typename NNNAME, typename ... AAARG > 62 | struct static_function_return_type 63 | { 64 | template< typename TTYPE, typename NNAME, typename ... AARG > 65 | struct inner 66 | { 67 | template< typename TYPE, typename NAME, typename ... ARG > 68 | static 69 | std::enable_if_t 70 | < 71 | has_static_function< TYPE, NAME, ARG ... >::value, 72 | decltype( 73 | helper< TYPE >::template call_static_function< TYPE, NAME >( 74 | std::declval< ARG >( ) ... ) ) 75 | >function( void * ); 76 | template< typename ... > 77 | static no_existence function( ... ); 78 | }; 79 | template< typename TTYPE, typename NNAME > 80 | struct inner< TTYPE, NNAME, void > 81 | { 82 | template< typename TYPE, typename NAME, typename ... > 83 | static decltype( 84 | helper< TYPE >::template call_static_function< TYPE, NAME >( ) ) function( void * ); 85 | template< typename ... > 86 | static no_existence function( ... ); 87 | }; 88 | typedef decltype( 89 | inner 90 | < 91 | TTTYPE, 92 | NNNAME, 93 | AAARG ... 94 | >::template function< TTTYPE, NNNAME, AAARG ... >( nullptr ) ) type; 95 | }; 96 | template< typename TYPE, typename NAME, typename ... ARG > 97 | struct call_static_function 98 | { 99 | decltype( helper< TYPE >::template call_static_function< TYPE, NAME >( std::declval< ARG >( ) ... ) ) 100 | operator ( )( const ARG & ... r ) 101 | { return helper< TYPE >::template call_static_function< TYPE, NAME >( r ... ); } 102 | }; 103 | template< typename TYPE, typename NAME > 104 | struct call_static_function< TYPE, NAME, void > 105 | { 106 | decltype( helper< TYPE >::template call_static_function< NAME, TYPE >( ) ) 107 | operator ( )( ) 108 | { return helper< TYPE >::template call_static_function< NAME, TYPE >( ); } 109 | }; 110 | #define DECLARE_ALL_POSSIBLE_STATIC_FUNCTION_HELPER( R, DATA, ELEMENT ) \ 111 | DECLARE_POSSIBLE_STATIC_FUNCTION( ELEMENT ) 112 | #define DECLARE_ALL_POSSIBLE_STATIC_FUNCTION( NAME_SEQ ) \ 113 | BOOST_PP_SEQ_FOR_EACH( DECLARE_ALL_POSSIBLE_STATIC_FUNCTION_HELPER, _, NAME_SEQ ) 114 | #endif //STATIC_FUNCTION_HPP 115 | -------------------------------------------------------------------------------- /static_variable.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STATIC_VARIABLE_HPP 2 | #define STATIC_VARIABLE_HPP 3 | #include 4 | #include "reflection.hpp" 5 | #include "has_class.hpp" 6 | #include 7 | #define DECLARE_POSSIBLE_STATIC_VARIABLE( NAME ) \ 8 | template< typename SELF, typename TAG > \ 9 | constexpr static bool has_static_variable( \ 10 | typename std::enable_if \ 11 | < \ 12 | std::is_same \ 13 | < \ 14 | TAG, \ 15 | ::tag< ::NAME > \ 16 | >::value && \ 17 | ! std::is_member_object_pointer< decltype( & SELF::NAME ) >::value \ 18 | >::type * ) \ 19 | { return true; } \ 20 | template< typename SELF, typename TAG > \ 21 | constexpr static typename \ 22 | std::enable_if \ 23 | < \ 24 | std::is_same \ 25 | < \ 26 | TAG, \ 27 | ::tag< ::NAME > \ 28 | >::value, \ 29 | bool \ 30 | >::type has_static_variable( ... ) { return false; } \ 31 | template< typename SELF, typename TAG > \ 32 | static typename \ 33 | std::add_lvalue_reference \ 34 | < \ 35 | typename enable_if_valid \ 36 | < \ 37 | typename std::enable_if \ 38 | < \ 39 | std::is_same \ 40 | < \ 41 | TAG, \ 42 | ::tag< ::NAME > \ 43 | >::value && \ 44 | ::has_static_variable< SELF, TAG >::value \ 45 | >::type, \ 46 | decltype( SELF::NAME ) \ 47 | >::type \ 48 | >::type static_variable( ) { return SELF::NAME; } \ 49 | template< typename SELF, typename TAG > \ 50 | static typename \ 51 | enable_if_valid \ 52 | < \ 53 | typename std::enable_if \ 54 | < \ 55 | std::is_same \ 56 | < \ 57 | TAG, \ 58 | ::tag< ::NAME > \ 59 | >::value \ 60 | >::type, \ 61 | decltype( SELF::NAME ) \ 62 | >::type static_variable_type( ); 63 | #define DECLARE_ALL_POSSIBLE_STATIC_VARIABLE_HELPER( R, TYPE, NAME ) \ 64 | DECLARE_POSSIBLE_STATIC_VARIABLE( NAME ) 65 | #define DECLARE_ALL_POSSIBLE_STATIC_VARIABLE( NAME_SEQ ) \ 66 | BOOST_PP_SEQ_FOR_EACH( DECLARE_ALL_POSSIBLE_STATIC_VARIABLE_HELPER, _, NAME_SEQ ) 67 | template< typename TYPE, typename TAG > 68 | struct has_static_variable 69 | { 70 | template< typename TTYPE, typename TTAG > 71 | constexpr static 72 | decltype( helper< TTYPE >::template has_static_variable< TTYPE, TTAG >( nullptr ) ) 73 | function( void * ) 74 | { return helper< TTYPE >::template has_static_variable< TTYPE, TTAG >( nullptr ); } 75 | template< typename ... > 76 | constexpr static bool function( ... ) { return false; } 77 | constexpr static bool value = function< TYPE, TAG >( nullptr ); 78 | }; 79 | template< typename TYPE, typename TAG > 80 | struct static_variable_type 81 | { 82 | template< typename TTYPE, typename TTAG > 83 | static 84 | std::enable_if_t 85 | < 86 | has_static_variable< TTYPE, TTAG >::value, 87 | decltype( helper< TTYPE >::template static_variable_type< TTYPE, TTAG >( ) ) 88 | > function( void * ); 89 | template< typename ... > 90 | static no_existence function( ... ); 91 | typedef decltype( function< TYPE, TAG >( nullptr ) ) type; 92 | }; 93 | template< typename TYPE, typename TAG > 94 | struct static_variable 95 | { 96 | template< typename TTYPE, typename TTAG > 97 | static decltype( helper< TTYPE >::template static_variable< TTYPE, TTAG >( ) ) function( void * ) 98 | { return helper< TTYPE >::template static_variable< TTYPE, TTAG >( ); } 99 | template< typename ... > 100 | static no_existence function( ... ) { return no_existence( ); } 101 | decltype( function< TYPE, TAG >( nullptr ) ) 102 | operator ( )( ) { return function< TYPE, TAG >( nullptr ); } 103 | }; 104 | #endif //STATIC_VARIABLE_HPP 105 | -------------------------------------------------------------------------------- /string_to_tag.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STRING_TO_TAG_HPP 2 | #define STRING_TO_TAG_HPP 3 | #include 4 | #include 5 | #include 6 | #include 7 | struct unable_to_determine_type : std::runtime_error 8 | { unable_to_determine_type( ) : std::runtime_error( "Unable to determine the type." ) { } }; 9 | #define STRING_TO_TAG_BASE_HANDLER_HELPER( R, DATA, ELEMENT ) \ 10 | virtual void string_to_tag_handle( const tag< ELEMENT > & ) const = 0; 11 | #define STRING_TO_TAG_HANDLER_HELPER( R, DATA, ELEMENT ) \ 12 | void string_to_tag_handle( const tag< ELEMENT > & e ) const { k( e ); } 13 | #define STRING_TO_TAG_HANDLER( NAME_SEQ ) \ 14 | struct string_to_tag_base_handler \ 15 | { \ 16 | virtual ~string_to_tag_base_handler( ) { } \ 17 | BOOST_PP_SEQ_FOR_EACH( STRING_TO_TAG_BASE_HANDLER_HELPER, _, NAME_SEQ ) \ 18 | }; \ 19 | template< typename K > \ 20 | struct string_to_tag_handler : string_to_tag_base_handler \ 21 | { \ 22 | const K & k; \ 23 | BOOST_PP_SEQ_FOR_EACH( STRING_TO_TAG_HANDLER_HELPER, _, NAME_SEQ ) \ 24 | string_to_tag_handler( const K & k ) : k( k ) { } \ 25 | }; 26 | 27 | #define STRING_TO_TAG_HELPER( R, DATA, ELEMENT ) \ 28 | tem.insert( std::make_pair( \ 29 | std::string( BOOST_PP_STRINGIZE( ELEMENT ) ), \ 30 | std::function< void( const string_to_tag_base_handler & ) >( \ 31 | []( const string_to_tag_base_handler & x ) \ 32 | { x.string_to_tag_handle( tag< ELEMENT >( ) ); } ) ) ); 33 | #define DECLARE_STRING_TO_TAG( NAME_SEQ ) \ 34 | STRING_TO_TAG_HANDLER( NAME_SEQ ) \ 35 | static \ 36 | std::map \ 37 | < \ 38 | std::string, \ 39 | std::function< void( const string_to_tag_base_handler & ) > \ 40 | > & reflection_map( ) \ 41 | { \ 42 | static std::map \ 43 | < \ 44 | std::string, \ 45 | std::function< void( const string_to_tag_base_handler & ) > \ 46 | > ret_map( []( ) \ 47 | { \ 48 | std::map \ 49 | < \ 50 | std::string, \ 51 | std::function< void( const string_to_tag_base_handler & ) > \ 52 | > tem; \ 53 | BOOST_PP_SEQ_FOR_EACH( STRING_TO_TAG_HELPER, _, NAME_SEQ ) \ 54 | return tem; \ 55 | }( ) ); \ 56 | return ret_map; \ 57 | } \ 58 | template< typename K > \ 59 | void string_to_tag( const std::string & str, const K & k ) \ 60 | { \ 61 | auto it = reflection_map( ).find( str ); \ 62 | if ( it == reflection_map( ).end( ) ) \ 63 | { throw unable_to_determine_type( ); } \ 64 | it->second( string_to_tag_handler< K >( k ) ); \ 65 | } 66 | #endif // STRING_TO_TAG_HPP 67 | -------------------------------------------------------------------------------- /test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EXAMPLE_HPP 2 | #define EXAMPLE_HPP 3 | #include 4 | #include 5 | #include "declare.hpp" 6 | #include "any.hpp" 7 | #include "../cpp_common/expansion.hpp" 8 | #include "object.hpp" 9 | #include 10 | #define BOOST_TEST_MAIN 11 | #define BOOST_TEST_DYN_LINK 12 | #include 13 | #define EXAMPLE_NAME_SEQ (data)(cache)(func)(function)(foo)(bar)(test)(any_test)(evil) 14 | DECLARE_NAMES( EXAMPLE_NAME_SEQ ) 15 | struct test : reflection_base< test > 16 | { 17 | int data = 12450; 18 | double func( int ) { return 10; } 19 | double func( int, int ) { return 10; } 20 | static int function( ) { return 1; } 21 | static long cache; 22 | static decltype( & function ) bar( long, long ) 23 | { return & function; } 24 | struct bad { auto operator & ( ) const { return & test::data; } }; 25 | static bad evil; 26 | }; 27 | 28 | DECLARE_ALL( EXAMPLE_NAME_SEQ ) 29 | test::bad test::evil = test::bad( ); 30 | long test::cache = 1230; 31 | DECLARE_ANY( any_test, EXAMPLE_NAME_SEQ ) 32 | static_assert( has_member_function< test, tag< func >, long, long >::value ); 33 | static_assert( ! has_member_function< test, tag< func >, void * >::value ); 34 | static_assert( std::is_same< 35 | member_function_return_type< test, tag< func >, double >::type, 36 | double >::value ); 37 | static_assert( ! has_static_function< test, tag< func >, void >::value ); 38 | static_assert( has_static_function< test, tag< function > >::value ); 39 | static_assert( ! has_static_function< test, tag< func > >::value ); 40 | static_assert( std::is_same< static_function_return_type< test, tag< function >, void >::type, int >::value ); 41 | static_assert( ! has_member_function< test, tag< function >, void >::value ); 42 | static_assert( ! has_static_function< test, tag< foo > >::value ); 43 | static_assert( has_static_variable< test, tag< cache > >::value ); 44 | static_assert( ! has_static_variable< test, tag< data > >::value ); 45 | static_assert( has_static_variable< test, tag< cache > >::value ); 46 | static_assert( std::is_same< static_variable_type< test, tag< cache > >::type, long >::value ); 47 | static_assert( has_static_function< test, tag< bar >, int, int >::value ); 48 | static_assert( 49 | std::is_same 50 | < 51 | decltype( call_static_function< test, tag< bar >, int, int >( )( 0, 1 )( ) ), 52 | int 53 | >::value ); 54 | static_assert( 55 | std::is_same 56 | < 57 | decltype( call_member_function< test, tag< func >, long >( )( std::declval< test >( ), ( 1 ) ) ), 58 | double 59 | >::value ); 60 | static_assert( has_class< test >::value ); 61 | static_assert( has_member_variable< test, tag< data > >::value ); 62 | static_assert( ! has_member_variable< test, tag< cache > >::value ); 63 | static_assert( std::is_same< member_variable_type< test, tag< data > >::type, int >::value ); 64 | static_assert( std::is_same< static_variable_type< test, tag< evil > >::type, test::bad >::value ); 65 | #include 66 | BOOST_AUTO_TEST_CASE( compiletime_reflection_test ) 67 | { 68 | BOOST_CHECK_EQUAL((static_variable< test, tag< cache > >( )( )), 1230); 69 | auto d = call_static_function< test, tag< bar >, int, int >( )( 0, 1 )( ); 70 | BOOST_CHECK_EQUAL( d, 1 ); 71 | } 72 | BOOST_AUTO_TEST_CASE( runtime_reflection_test ) 73 | { 74 | using common::make_expansion; 75 | auto f = [](...){ BOOST_CHECK( false ); }; 76 | auto ii = make_expansion( 77 | [](int i){ std::cout << i << std::endl; }, 78 | [](...){ std::cout << "Hello World" << std::endl; } ); 79 | test t; 80 | invoke_all_member_variable( 81 | t, 82 | make_expansion( []( tag< data >, int i ){ std::cout << i << std::endl; }, [](...){} ) ); 83 | t.get_member_variable( "data", 84 | make_expansion( []( int i ){ BOOST_CHECK_EQUAL( i, 12450 ); }, f ) ); 85 | t.get_static_variable( "cache", make_expansion( []( int i ){ BOOST_CHECK_EQUAL( i, 1230 ); }, f ) ); 86 | BOOST_CHECK( t.has_member_variable( "data" ) ); 87 | BOOST_CHECK( ! t.has_member_variable( "cache" ) ); 88 | BOOST_CHECK( t.has_static_variable( "cache" ) ); 89 | t.call_member_function( "func", 1, ii ); 90 | t.call_static_function( "function", ii ); 91 | t.call_member_function( "function", ii ); 92 | BOOST_CHECK( ! t.has_static_function< int >( "func" ) ); 93 | BOOST_CHECK( t.has_member_function< int >( "func" ) ); 94 | t.member_variable_type( 95 | "data", 96 | make_expansion( [](tag){ }, f ) ); 97 | t.static_variable_type( 98 | "cache", 99 | make_expansion( [](tag){ }, f ) ); 100 | t.member_function_return_type< int >( "func" )( 101 | make_expansion( [](tag){ }, f ) ); 102 | t.static_function_return_type( "function" )( 103 | make_expansion( [](tag){ }, f ) ); 104 | } 105 | BOOST_AUTO_TEST_CASE( any_reflection_test ) 106 | { 107 | using common::make_expansion; 108 | auto f = [](...){ BOOST_CHECK( false ); }; 109 | any_test tr( []( ){ test t; return t; }( ) ); 110 | auto ii = make_expansion( 111 | [](int i){ std::cout << i << std::endl; }, 112 | [](...){ std::cout << "Hello World" << std::endl; } ); 113 | tr.member_variable_type( 114 | "data", 115 | make_expansion( [](tag){ }, f ) ); 116 | tr.get_member_variable( "data", ii ); 117 | tr.get_static_variable( "cache", ii ); 118 | BOOST_CHECK( tr.has_member_variable( "data" ) ); 119 | BOOST_CHECK( ! tr.has_member_variable( "cache" ) ); 120 | BOOST_CHECK( tr.has_static_variable( "cache" ) ); 121 | tr.call_member_function( "func", 1, ii ); 122 | tr.call_static_function( "function", ii ); 123 | tr.call_member_function( "function", ii ); 124 | BOOST_CHECK( ! tr.has_static_function< int >( "func" ) ); 125 | BOOST_CHECK( tr.has_member_function< int >( "func" ) ); 126 | tr.static_variable_type( 127 | "cache", 128 | make_expansion( [](tag){ }, f ) ); 129 | tr.member_function_return_type< tag< func >, int >( )( 130 | make_expansion( [](tag){ }, f ) ); 131 | tr.static_function_return_type< tag< function > >( )( 132 | make_expansion( [](tag){ }, f ) ); 133 | } 134 | BOOST_AUTO_TEST_CASE( object_reflection_test ) 135 | { 136 | auto f = [](...){ BOOST_CHECK( false ); }; 137 | object< any_test > ob; 138 | any_test tr( []( ){ test t; return t; }( ) ); 139 | ob.add_member_variable( "mem", tr ); 140 | BOOST_CHECK( ob.has_member_variable( "mem" ) ); 141 | BOOST_CHECK( ! ob.has_member_variable( "noexist" ) ); 142 | ob.member_variable_type( "mem", common::make_expansion( []( const tag< test > & ){ }, f ) ); 143 | } 144 | #endif //EXAMPLE_HPP 145 | --------------------------------------------------------------------------------