├── .gitignore ├── CMakeLists.txt ├── README.md ├── doc ├── .gitignore ├── CMakeLists.txt ├── cli.dox ├── doxygen.cfg ├── footer.html ├── main_page.dox ├── quickstart.dox └── vtable.dox ├── examples ├── .gitignore ├── CMakeLists.txt ├── calculator.hpp ├── cli.hpp ├── rpc.hpp ├── rpc_client.cpp ├── rpc_server.cpp ├── signal.cpp ├── simple.cpp └── value_test.cpp ├── include ├── CMakeLists.txt └── boost │ └── reflect │ ├── any_ptr.hpp │ ├── detail │ ├── get_field.hpp │ ├── iterator.ipp │ ├── iterator_impl.hpp │ ├── place_holder.hpp │ ├── value.ipp │ ├── value_base.ipp │ ├── value_cref.ipp │ └── value_ref.ipp │ ├── error.hpp │ ├── iterator.hpp │ ├── mirror_interface.hpp │ ├── old.hpp │ ├── reflect.hpp │ ├── reflect_function_signature.hpp │ ├── typeinfo.hpp │ ├── value.hpp │ ├── value_base.hpp │ ├── value_cref.hpp │ ├── value_ref.hpp │ ├── value_visitor.hpp │ ├── void.hpp │ └── vtable.hpp └── tests ├── CMakeLists.txt └── value_test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /CMakeFiles/ 2 | /Makefile 3 | /cmake_install.cmake 4 | examples/cmake_install.cmake 5 | 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if( ENABLE_EXAMPLES ) 2 | option( ENABLE_REFLECT_EXAMPLES "Build Boost.Reflect Examples" ON ) 3 | if( ENABLE_REFLECT_EXAMPLES ) 4 | add_subdirectory(examples) 5 | add_subdirectory(tests) 6 | endif( ENABLE_REFLECT_EXAMPLES ) 7 | endif( ENABLE_EXAMPLES ) 8 | install( DIRECTORY include/boost/reflect DESTINATION include/boost ) 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Boost.Reflect - Simple Reflection Library 2 | --------------------------------------- 3 | 4 | The Boost Reflect library provides a means to describe the interface 5 | of a class or struct to provide compile-time and run-time reflection. 6 | 7 | Some of the useful features provided by the Reflect library include: 8 | 9 | * boost::reflect::any - a class that can contain any object 10 | that implements Interface. 11 | * Use visitors to create dynamic interfaces. 12 | - RPC client/server stubs 13 | - Command Line Interface 14 | - Scripting Interfaces 15 | - Asynchronous Actors 16 | 17 | 18 | Example: Simple Command Line Calculator 19 | --------------------------------------- 20 | 21 | An [example](https://github.com/bytemaster/boost_reflect/blob/master/examples/simple.cpp) 22 | of how to create a command line calculator can be found in the examples directory. 23 | 24 | 25 | #include 26 | 27 | struct calculator { 28 | calculator():result_(0){} 29 | double add( double v ) { return result_ += v; } 30 | double sub( double v ) { return result_ -= v; } 31 | double result() { return result_; } 32 | 33 | private: 34 | double result_; 35 | }; 36 | 37 | BOOST_REFLECT_ANY( calculator, (add)(sub)(result) ) 38 | 39 | int main( int argc, char** argv ) { 40 | boost::reflect::any_ptr s( new CalculatorService() ); 41 | printf( "Result: %f\n", s->result() ); 42 | 43 | cli m_cli(s); 44 | 45 | std::string line; 46 | std::string cmd; 47 | std::string args; 48 | 49 | while( true ) { 50 | std::cerr << "Enter Method: "; 51 | std::getline( std::cin, line ); 52 | cmd = line.substr( 0, line.find('(') ); 53 | args = line.substr( cmd.size(), line.size() ); 54 | std::cerr << m_cli[cmd](args) << std::endl; 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | ### Output ### 61 | 62 | add double(double) 63 | sub double(double) 64 | result double()const 65 | 66 | Enter Method: add(5) 67 | 5 68 | Enter Method: sub(3) 69 | 2 70 | Enter Method: result() 71 | 2 72 | 73 | Boost.CMT can be built by checking out my development repository: https://github.com/bytemaster/dev 74 | 75 | ### Installation ## 76 | 77 | git clone https://github.com/bytemaster/dev 78 | cd dev 79 | git submodule init 80 | git submodule update 81 | cmake . 82 | make 83 | make install 84 | @endcode 85 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | /doc/ 2 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | include(BoostDocs) 3 | -------------------------------------------------------------------------------- /doc/cli.dox: -------------------------------------------------------------------------------- 1 | /** 2 | @defgroup boost_reflect_cli_example Command Line Interpreter Example 3 | @ingroup boost_reflect 4 | 5 | This example demonstrates how Boost.Reflect can be used to create a generic 6 | command line interpreter that can interpret std::cin commands like: 7 | 8 | @code 9 | add( 1 ) 10 | add2( 1,2.4 ) 11 | @endcode 12 | 13 | And call the proper method with the proper arguments and then print the result. 14 | 15 | 16 | @code 17 | class cli 18 | { 19 | public: 20 | template 21 | cli( T aptr) { 22 | boost::reflect::visit( aptr, visitor( *this, *aptr) ); 23 | } 24 | 25 | boost::function& operator[]( const std::string& name ) 26 | { return methods[name]; } 27 | 28 | private: 29 | template struct visitor { 30 | visitor( cli& c, VTableType& vtbl ):m_cli(c),m_vtbl(vtbl){} 31 | template 32 | void operator()( const char* name ) const { 33 | std::cerr << std::setw(10) << std::setiosflags(std::ios::left) << name 34 | << " " << boost::reflect::get_typename() 35 | << (M::is_const ? "const" : "") <(m_vtbl.*m); 37 | } 38 | VTableType& m_vtbl; 39 | cli& m_cli; 40 | }; 41 | 42 | template 43 | struct cli_functor 44 | { 45 | cli_functor( Functor f ) 46 | :m_func(f){} 47 | 48 | typedef typename boost::remove_reference::type functor_type; 49 | 50 | std::string operator()( const std::string& cli ) { 51 | std::stringstream ss(cli); 52 | Seq s; ss >> boost::fusion::tuple_delimiter(',') >> s; 53 | std::stringstream rtn; 54 | rtn << m_func(s); 55 | return rtn.str(); 56 | } 57 | Functor m_func; 58 | }; 59 | std::map > methods; 60 | }; 61 | 62 | @endcode 63 | 64 | This class can then be used like so: 65 | 66 | 67 | @code 68 | int main( int argc, char** argv ) 69 | { 70 | boost::reflect::any_ptr s( new CalculatorService() ); 71 | printf( "Result: %f\n", s->result() ); 72 | 73 | cli m_cli(s); 74 | 75 | std::string line; 76 | std::string cmd; 77 | std::string args; 78 | 79 | while( true ) { 80 | std::cerr << "Enter Method: "; 81 | std::getline( std::cin, line ); 82 | cmd = line.substr( 0, line.find('(') ); 83 | args = line.substr( cmd.size(), line.size() ); 84 | std::cerr << m_cli[cmd](args) << std::endl; 85 | } 86 | 87 | return 0; 88 | } 89 | @endcode 90 | 91 | */ 92 | -------------------------------------------------------------------------------- /doc/footer.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 7 | 9 | 12 | 13 |
5 | © Daniel Larimer 2010-2011 - Licensed under Boost Software License, Version 1.0 6 | 8 | 10 | $projectname 11 |
14 | 27 | -------------------------------------------------------------------------------- /doc/main_page.dox: -------------------------------------------------------------------------------- 1 | /** 2 | @defgroup boost_reflect Boost.Reflect 3 | 4 | The Boost Reflect library provides a means to quickly describe the interface of 5 | a class or struct and then use that description to provide compile-time and 6 | run-time reflection on the interface. 7 | */ 8 | 9 | /** 10 | @defgroup boost_reflect_introduction Introduction 11 | @ingroup boost_reflect 12 | 13 | There have been many libraries that attempt to provide Reflection tools for 14 | C++ programs. The most robust solution is the 15 | Boost Mirror library. 16 | Despite its ability to reflect just about every c++ construct, the Boost Mirror library 17 | requires the developer to enter more text to describe the interface than it took to 18 | write the interface in the first place. 19 | 20 | Boost.Reflect attempts to find a middle ground with a focus on providing the most useful 21 | features while minimizing the amount of work a developer must do to reflect 22 | those properties. Boost.Reflect goes one step further and provides a generic Type Erasure 23 | construct, boost::reflect::any_ptr. 24 | 25 | @section boost_reflect_motivation Motivation 26 | 27 | It is not uncommon for developers to write some code that needs to interface 28 | with many different systems in slightly different ways. The result is ususally 29 | the creation of many different "wrappers" each exposing the core function of 30 | an object in a slightly different way. 31 | 32 | - Remote Procedure Client / Server Stubs 33 | - Scripting Language Hooks 34 | - Type Erasure Interfaces 35 | - Command Line Arguments 36 | - Actor Paradigmn 37 | - Configuration 38 | 39 | All of these tasks represent the creation of code that is derived from 40 | the core interface in a well defined manner. Each wrapper is tightly 41 | coupled to the core interface, such that if the core interface changes then 42 | all the wrappers must make a similar change. Coding these wrappers is the 43 | type of task that makes your hands ache just thinking about all of the 44 | mindless typing involved. 45 | 46 | @section boost_reflect_reflection Reflection 47 | 48 | The reflection provided by Boost.Reflect focuses on exposing typenames, inheritance, 49 | return values, method names, parameter types, constness, and public 50 | members. All reflection is non-invasive and may be added to any 51 | class or struct. 52 | 53 | @section boost_reflect_type_erasure Type Erasure 54 | 55 | In the world of generic programming, type information tends to propogate as 56 | template parameters. "Type Erasure is the process of turning a wide variety of 57 | types with a common interface into one type with that same interface." 58 | 59 | - C++ Template Metaprogramming by Dave Abrahams & Aleksy Curtovoy 60 | 61 | Common uses of type erasure include boost::any and boost::function. Boost.Any 62 | erases all type information except its name and copy semantics. Boost.Function 63 | erases everything about a type except the calling signature. Algorithms written 64 | with Boost.Any and Boost.Function can be agnostic to the huge amount of type 65 | variation possible for functors, function pointers, member function pointers, 66 | or storage. 67 | 68 | This article on type erasure 69 | shows how Generic Programming (Templates) often conflicts with good Object Oriented design 70 | because generic programing exposes the internal implementation details that good 71 | Object Oriented design goes to great lengths to hide. 72 | 73 | 74 |
75 | Good engineering involves compromise at every turn. A good, working, 76 | finished product is never pure by the standards of any one idiom or 77 | methodology. The art of good engineering is not the art of 78 | discovering and applying the one right idiom over all others. The 79 | art of good engineering is to know what your options are, and then 80 | to choose your trade-offs wisely rather than letting others choose 81 | them for you. 82 |
83 | 84 | I found the following quote from the article really helps put the debate between 85 | 'fast' generic programing and 'slow' object oriented programming. 86 | 87 |
88 | Optimization whose effect no user ever notices is the root of many evils, among them the failure of software projects and the subsequent failure of businesses. 89 |
90 | 91 | Boost.Reflect focuses on being as efficeint as possible without sacraficing 92 | development speed and proper Object Oriented abstraction. If you don't 93 | use boost::reflect::any_ptr in your inner loops, then your users will 94 | never notice one extra layer of indirection or an extra couple of bytes of 95 | RAM. Your company, managers, and customers will notice the cost savings in 96 | reducing your development time, decouping components, and added resiliance 97 | to change that developing with Boost.Reflect can provide through type erasure. 98 | */ 99 | /** 100 | @mainpage 101 | 102 | The Boost Reflect library provides a means to quickly describe the interface of 103 | a class or struct and then use that description to provide compile-time and 104 | run-time reflection on the interface. 105 | 106 | 107 | @note This library is not part of the official Boost C++ libraries. It was developed 108 | with the intention of being submitted for review by the Boost community and therefore 109 | everything is coded accoding to the Boost C++ Coding Guidlines. 110 | 111 | @section toc Table of Contents 112 | 113 | - @ref boost_reflect_introduction 114 | - @ref boost_reflect_motivation 115 | - @ref boost_reflect_reflection 116 | - @ref boost_reflect_type_erasure 117 | - @ref boost_reflect_quickstart 118 | - @ref boost_reflect_basic 119 | - @ref boost_reflect_erasures 120 | - @ref boost_reflect_vtable 121 | - @ref boost_reflect_rationale 122 | - @ref boost_reflect_acknowledgements 123 | 124 | */ 125 | 126 | /** 127 | @defgroup boost_reflect_rationale Design Rationale 128 | @ingroup boost_reflect 129 | 130 | There has been discussion on the Boost mailing list regarding how 131 | the type erasure should be implemented. The obvious, "ideal", 132 | would be something where the 'weight' of the any_ptr<> is no more 133 | than boost::any. This approach would 'convert' any type passed 134 | into the constructor into a polymorphic type implementing the interface. 135 | Then the cost of a call is one virtual method invocation 136 | (assuming proper inlining). 137 | 138 | This solution has already been implemented via 139 | Boost.Interfaces. 140 | 141 | The interface declaration used by Boost.Interfaces is: 142 | 143 | @code 144 | BOOST_INTERFACE_BEGIN(IShape) 145 | BOOST_INTERFACE_CONST_FUNCTION0(GetX, int) 146 | BOOST_INTERFACE_CONST_FUNCTION0(GetY, int) 147 | BOOST_INTERFACE_CONST_FUNCTION0(GetArea, double) 148 | BOOST_INTERFACE_FUNCTION2(SetXY, void, (int, x), (int, y)) 149 | BOOST_INTERFACE_FUNCTION2(OffSetXY, void, (int, x), (int, y)) 150 | BOOST_INTERFACE_CONST_FUNCTION0(GetName, const char*) 151 | BOOST_INTERFACE_END(IShape) 152 | @endcode 153 | 154 | Unfortunately, there is no clear way to define a macro based solution that 155 | achieves what Boost.Interfaces achieves without specifying your entire 156 | interface with the (relatively) messy syntax above. A downside to the approach above 157 | is that any types that happen to contain a ',' would require special handling. 158 | A benefit to the above approach is that there is potential for knowng the 159 | parameter names in addition to the types. 160 | 161 | I opted for a simpler syntax that can apply to pre-existing types along with the potential 162 | for more dynamic interface implementations rather than going for maximum possible performance 163 | or the minimum possible memory usage. With the proper "InterfaceDelegate", there is the potential 164 | that each method turns into a Don Clugston fast delegate. Thus you can get 165 | the 'fastest possible delegation' at the price of 16 bytes per method 166 | (on 64 bit machines) and a little extra one-time initialization cost. 167 | 168 | */ 169 | 170 | /** 171 | @defgroup boost_reflect_acknowledgements Acknowledgements 172 | @ingroup boost_reflect 173 | 174 | Ideas, inspiration, and code were borrowed from: 175 | - Boost.Interfaces - Jonathan Turkanis & Christopher Diggins. 176 | - Boost.Mirror - Matus Chochlik. 177 | - Fast Delegate - Don Clugston. 178 | - C++ Template Metaprogramming by Dave Abrahams & Aleksy Curtovoy 179 | - On the Tension Between Object-Oriented and Generic Programming in C++ 180 | and What Type Erasure Can Do About It by Thomas Becker 181 | 182 | 183 | */ 184 | -------------------------------------------------------------------------------- /doc/quickstart.dox: -------------------------------------------------------------------------------- 1 | /** 2 | @defgroup boost_reflect_quickstart Quick Start 3 | @ingroup boost_reflect 4 | 5 | There are two primary uses for the Boost.Reflect library: 6 | 7 | - Visiting members on a type. 8 | - Creating type erasures for an interface 9 | 10 | @section boost_reflect_basic Basic Reflection 11 | 12 | Basic reflection of a type is achieved using the @ref BOOST_REFLECT(TYPE,INHERITS,MEMBERS) 13 | macro to specify base classes and class members. Below is an example of reflecting 14 | a struct. 15 | 16 | @code 17 | struct my_struct { 18 | int hello; 19 | std::string world; 20 | }; 21 | BOOST_REFLECT( my_struct, (hello)(world) ) 22 | @endcode 23 | 24 | Now that we have reflected the struct, we can dump it to XML with a 25 | simple visitor. 26 | 27 | @code 28 | template 29 | struct xml_printer { 30 | xml_printer( const T& c ):self(c){} 31 | 32 | template 33 | static xml_printer make( const Type& t ) { 34 | return xml_printer(t); 35 | } 36 | 37 | template 38 | void operator()( const char* name )const { 39 | std::cerr<<"<"<"<<(self.*p)<<"\n"; 40 | } 41 | const T& self; 42 | }; 43 | @endcode 44 | 45 | The visitor can then be applied like so: 46 | @code 47 | my_struct s; 48 | boost::reflect::reflector::visit( xml_printer(s) ); 49 | boost::reflect::reflector::visit( xml_printer::make(s) ); 50 | @endcode 51 | 52 | 53 | @section boost_reflect_erasures Type Erasures 54 | 55 | Type Erasure is one means to hide implementation details by defining a type 56 | that can contain any object that implements the required interface. Examples are 57 | boost::any and boost::function. Boost.Reflect enables the rapid generation of 58 | new type erasures for arbitrary interfaces via the @link boost::reflect::any_ptr any_ptr @endlink type. 59 | 60 | boost::reflect::any_ptr can hold a pointer or shared pointer to any type that 61 | implements a particular reflected interface. 62 | 63 | Here is an example on how to define a new type erasure for two interfaces, 64 | Service and Calculator. 65 | 66 | @code 67 | struct Service { 68 | std::string name()const; 69 | int exit(); 70 | }; 71 | struct Calculator : Service { 72 | double add( double v ); 73 | double sub( double v ); 74 | double mult( double v ); 75 | double div( double v ); 76 | double result()const; 77 | }; 78 | 79 | BOOST_REFLECT_ANY( Service,(name)(exit) ) 80 | BOOST_REFLECT_ANY_DERIVED( Calculator, (Service), (add)(sub)(mult)(div)(result) ) 81 | @endcode 82 | 83 | @note When you define an interface, you need not provide implementations of the methods; however, 84 | if you want you may also use an interace like any other class without limititations. 85 | 86 | 87 | @code 88 | class CalculatorService { 89 | public: 90 | CalculatorService():m_result(0){} 91 | 92 | std::string name()const { return "CalculatorService"; } 93 | int exit() { ::exit(0); } 94 | double add( double v ) { return m_result += v; } 95 | double sub( double v ) { return m_result -= v; } 96 | double mult( double v ) { return m_result *= v; } 97 | double div( double v ) { return m_result /= v; } 98 | double result()const { return m_result; } 99 | 100 | private: 101 | double m_result; 102 | }; 103 | 104 | void try_it() { 105 | reflect::any_ptr calc( new CalculatorService() ); 106 | calc->add(5); 107 | calc->add(6); 108 | std::string name = calc->name(); 109 | assert( calc->result() == 11 ); 110 | } 111 | @endcode 112 | 113 | Some things to note, CalculatorService did not inherit either Calculator or Service, 114 | it simply exposed all of the methods defined by the interface. If it looks like a 115 | Duck, quacks like a Duck, then it is a Duck. 116 | 117 | The interface of any_ptr is 'identical' to the Calculator defined above. 118 | 119 | Pointer semantics were chosen to discourage using reflect::anys as values where assignment and 120 | copy construction creates a new instance. Initialization of @link boost::reflect::any_ptr 121 | any_ptr @endlink with a new pointer is a relatively expensive operation and value semantics 122 | would create objects that are much bigger and more expensive to copy than traditional types 123 | as each method is a functor that must be initialized at copy/construction time. 124 | 125 | Generally speaking, any_ptr<> should be used to abstract long-lived objects and not for 126 | temporaries. 127 | */ 128 | -------------------------------------------------------------------------------- /doc/vtable.dox: -------------------------------------------------------------------------------- 1 | /** 2 | @defgroup boost_reflect_vtable Dynamic VTables 3 | @ingroup boost_reflect 4 | 5 | In C++ vtables enable virtual methods and runtime polymorphism. Boost.Reflect implements 6 | a much more powerful and dynamic version of vtables with boost::reflect::vtable. Unlike normal 7 | vtables, which are statically populated at compile time, boost::reflect::vtable can change 8 | dynamically at runtime and can be populated from any type that implements its interface. 9 | 10 | Traditional C++ vtables provide one global instance and all objects of a particular type 11 | point to that single instance. Boost.Reflect's vtable provides a unique copy per instance 12 | as each instance is dynamically bound. 13 | 14 | Furthermore, boost::reflect::vtable allows any Functor to be assigned. 15 | 16 | @section boost_reflect_vtable_definition Creating a new Dynamic VTable 17 | 18 | Like regular C++ vtables, you must define the signature of your methods. 19 | 20 | @code 21 | struct Service { 22 | std::string name()const; 23 | }; 24 | struct Calculator : Service { 25 | double add( double v ); 26 | }; 27 | 28 | BOOST_REFLECT_ANY( Service,(name) ) 29 | BOOST_REFLECT_ANY_DERIVED( Calculator, (Service), (add) ) 30 | @endcode 31 | 32 | These macros expand into something morally equal to: 33 | 34 | @code 35 | namespace boost { namespace reflect { 36 | template 37 | struct vtable { 38 | typedef Service interface_type; 39 | boost::function name; 40 | }; 41 | template 42 | struct vtable : vtable { 43 | typedef Calculator interface_type; 44 | boost::function add; 45 | }; 46 | } } 47 | @endcode 48 | 49 | The result is that you can use a vtable like so: 50 | 51 | @code 52 | std::string get_name() { return "hello world"; } 53 | double do_add(double v) { return v+3.1415; } 54 | 55 | vtable calc; 56 | calc.name = get_name; 57 | calc.add = do_add; 58 | 59 | BOOST_ASSERT( calc.name() == "hello world" ); 60 | BOOST_ASSERT( calc.add(5) == 8.1415 ); 61 | @endcode 62 | 63 | That by itself is useful, but not all that special. The power of boost::vtable is 64 | that it supports an InterfaceDelegate to define how member pointers are mapped to 65 | function objects, and they support reflection allowing you to visit each member. 66 | 67 | The default InterfaceDelegate is boost::reflect::mirror_interface which attempts to 68 | mirror the interface of Service and Calculator without modifying return types, parameters, 69 | constness, or adding other operations. 70 | 71 | @section boost_reflect_interface_delegate VTable Interface Delegates 72 | 73 | An interface delegate takes the form of a template meta-function that calculates the 74 | functor type for a given member pointer and provides a visitor that can be used to 75 | initialize your calculated types from a reference to an instance of any type that 76 | provides the same interface. 77 | 78 | @code 79 | struct your_delegate { 80 | template 81 | struct calculate_type { 82 | typedef your_member_functor_type type; 83 | }; 84 | 85 | template 86 | struct set_visitor { 87 | set_visitor( VTableType& vt, AssignType& self ); 88 | 89 | template 90 | void operator()( MemberFunctor VTable::* m, const char* name )const; 91 | }; 92 | }; 93 | @endcode 94 | 95 | In the case of boost::reflect::mirror_interface you end up with: 96 | 97 | @code 98 | struct mirror_interface 99 | { 100 | template 101 | struct calculate_type { 102 | typedef mirror_member type; 103 | }; 104 | // set_visitor omited... for now 105 | }; 106 | @endcode 107 | 108 | Which, for every mirrored member defines a type of mirror_member<> which is implemented as: 109 | 110 | @code 111 | template 112 | struct mirror_member 113 | { 114 | // boost::result_of 115 | typedef typename adapt_void::result_type result_type; 116 | typedef mirror_member self_type; 117 | typedef boost::fusion::vector fused_params; 118 | typedef boost::function_traits traits; 119 | static const bool is_const = true; 120 | static const bool is_signal = false; 121 | 122 | typedef typename boost::remove_pointer::type signature; 123 | 124 | result_type operator()( PARAM_ARGS )const { 125 | return m_delegate( boost::fusion::make_vector(PARAM_NAMES) ); 126 | } 127 | result_type operator() ( const fused_params& fp )const { 128 | return m_delegate( fp ); 129 | } 130 | mirror_member& operator=( const mirror_member& d ) { 131 | m_delegate = d.m_delegate; 132 | return *this; 133 | } 134 | template 135 | mirror_member& operator=( const T& d ) { 136 | m_delegate = adapt_void(d); 137 | return *this; 138 | } 139 | template 140 | void set_delegate( C* s, M m ) { 141 | m_delegate = adapt_void >( 142 | boost::fusion::make_fused_function_object( 143 | boost::bind(m,s PARAM_PLACE_HOLDERS ) )); 144 | } 145 | private: 146 | boost::function m_delegate; 147 | }; 148 | @endcode 149 | 150 | First thing you will realize is that each functor provides a lot of typedefs that 151 | are useful for meta-programming. The second thing you will notice is that the mirrored 152 | interface is actually a bit more that simply mirroring the interface, it also supports boost::fusion's 153 | fused parameters interface. This greatly simplifies writing generic code for a particular interface. 154 | 155 | @todo Should boost::reflect::mirror_interface be true to its name and not add other operations 156 | such as fused parameter lists and instead create a boost::reflect::fused_interface? Unless it 157 | is found to cause conflicts, the extra function of mirror_interface is probably better than the 158 | extra complications of switching between fused/unfused interfaces. 159 | 160 | 161 | In addition to providing fused parameters, the mirror_interface also adapts void return types 162 | into void_t return types. This greatly simplifies meta programming. 163 | 164 | 165 | @section boost_reflect_vtable_delegate_set_visitor VTable Delegate set_visitors. 166 | 167 | The purpose of the InterfaceDelegate::set_visitor struct is to assign your calculated functor from 168 | an arbitrary type's member function with the same name and signature. The set_visitor is called with 169 | a member pointer on a boost::reflect::vtable to your calculated functor type. This visitor is templated 170 | on the arbitrary type being assigned to the vtable and so now you must assign your functor from T::name 171 | which is challenging because the visitor doesn't know the 'name' on T except as a const char*. This is worked 172 | around because the Functor defined by BOOST_REFLECT_ANY() provides a useful static method: 173 | 174 | @code 175 | template \ 176 | static void get_member_ptr( AssignType v ) { v = &Type::elem; } \ 177 | @endcode 178 | 179 | This can then be used like so: 180 | 181 | @code 182 | template 183 | class set_visitor { 184 | public: 185 | set_visitor( VTableType& vt, T& self ) 186 | :m_self(self),vtable(vt){} 187 | 188 | template 189 | void operator()( M InterfaceName::* m, const char* name )const { 190 | assign a(m_self,vtable.*m); 191 | M::template get_member_ptr( a ); 192 | } 193 | private: 194 | template 195 | struct assign { 196 | assign( T& _v, Member& _m ):v(_v),m(_m){} 197 | 198 | template 199 | void operator=( const MemberPtr& p ) { 200 | m.set_delegate( &v, p ); 201 | } 202 | private: 203 | T& v; 204 | Member& m; 205 | }; 206 | T& m_self; 207 | VTableType& vtable; 208 | }; 209 | @endcode 210 | 211 | Using this method you can create arbitrary helper structs that can assign your 212 | delegate functors from an arbitrary member ptr. 213 | 214 | But wait, if you were observant you would realize that we never defined get_member_ptr() for our 215 | mirror_member<> type. This is where the BOOST_REFLECT_ANY() macro brings it all together. 216 | 217 | BOOST_REFLECT_ANY( interface_type, (method_name) ), boost::reflect::vtable is actually defined as: 218 | 219 | @code 220 | struct vtable { 221 | struct __reflect__method_name 222 | public InterfaceDelegate::calculate_type::type 223 | { 224 | static const char* name() { return "method_name"; } 225 | template 226 | static void get_member_ptr( AssignType v ) { v = &Type::elem; } 227 | } method_name; 228 | }; 229 | @endcode 230 | 231 | So your calculated functor type is uniquely derived from for each name and thus provides the required 232 | get_member_ptr() function. get_member_ptr() does not return &Type::elem because 233 | of the complex issues around knowing that the return type *should be*. By passing in an arbitrary type which 234 | is then assigned the result of &Type::elem you are given the benefit of argument deduction and matching. 235 | 236 | As a consequence of this design you can actualy use boost::reflect::any_ptr to do some nifty things like: 237 | 238 | @code 239 | boost::reflect::vtable::method_name::name(); 240 | boost::reflect::vtable::method_name::get_member_ptr(...) 241 | @endcode 242 | */ 243 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | /CMakeFiles/ 2 | /Makefile 3 | /reflect_signal 4 | /reflect_simple 5 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( ../include ) 2 | include_directories( ../../atomic/include ) 3 | include_directories( ../../cmt/include ) 4 | include_directories( ../../move/include ) 5 | SET( libraries 6 | #/usr/local/lib/tcmalloc/libtcmalloc.a 7 | boost_cmt 8 | boost_context 9 | ${Boost_THREAD_LIBRARY} 10 | ${Boost_ASIO_LIBRARY} 11 | ${Boost_SYSTEM_LIBRARY} 12 | ${Boost_SIGNALS_LIBRARY}) 13 | 14 | #add_executable( reflect_signal signal.cpp ) 15 | #target_link_libraries( reflect_signal ${libraries} ) 16 | -------------------------------------------------------------------------------- /examples/calculator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_IDL_CALCULATOR_HPP 2 | #define _BOOST_IDL_CALCULATOR_HPP 3 | 4 | #include 5 | #include 6 | struct Service 7 | { 8 | std::string name()const; 9 | int exit(); 10 | }; 11 | struct Calculator : Service 12 | { 13 | double add( double v ); 14 | double add2( double v, double v2 ); 15 | double sub( double v ); 16 | double mult( double v ); 17 | double div( double v ); 18 | double result()const; 19 | }; 20 | 21 | BOOST_IDL_INTERFACE( Service, BOOST_PP_SEQ_NIL, (name)(exit) ) 22 | BOOST_IDL_INTERFACE( Calculator, (Service), (add)(add2)(sub)(mult)(div)(result) ) 23 | 24 | #endif // _BOOST_IDL_CALCULATOR_HPP 25 | -------------------------------------------------------------------------------- /examples/cli.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_IDL_CLI_HPP_ 2 | #define _BOOST_IDL_CLI_HPP_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | inline std::string cin_getline() { 12 | std::string s; 13 | std::getline( std::cin, s ); 14 | return s; 15 | } 16 | 17 | /** 18 | * Takes any interface object and provides a command line interface for it. 19 | */ 20 | class cli { 21 | public: 22 | template 23 | cli( AnyPtr aptr):my_ptr(aptr) { 24 | // AnyPtr will create a copy which will go out of scope unless we 25 | // are smart about keeping a reference to it. 26 | boost::reflect::visit( aptr, visitor( *this, **boost::any_cast(&my_ptr)) ); 27 | } 28 | ~cli() { 29 | try { 30 | read_done.wait(); 31 | } catch ( ... ) { 32 | } 33 | } 34 | 35 | boost::function& operator[]( const std::string& name ) 36 | { return methods[name]; } 37 | 38 | void start() { 39 | read_done = boost::cmt::async( boost::bind( &cli::read_loop, this ) ); 40 | } 41 | 42 | private: 43 | boost::any my_ptr; 44 | 45 | boost::cmt::future read_done; 46 | void read_loop() { 47 | boost::cmt::thread* getline_thread = boost::cmt::thread::create(); 48 | while( true ) 49 | { 50 | std::string cmd, line, args; 51 | std::cerr << "Enter Method: "; 52 | line = getline_thread->sync( cin_getline ); 53 | cmd = line.substr( 0, line.find(' ') ); 54 | args = line.substr( cmd.size(), line.size() ); 55 | try { 56 | std::cerr << methods[cmd](args) << std::endl; 57 | } catch ( const std::exception& e ) { 58 | std::cerr << e.what() << std::endl; 59 | } 60 | } 61 | } 62 | 63 | template struct visitor { 64 | visitor( cli& c, VTableType& vtbl ):m_cli(c),m_vtbl(vtbl){} 65 | /* 66 | template 67 | void operator()( const char* name ) const { 68 | std::cerr << std::setw(10) << std::setiosflags(std::ios::left) << std::string("'")+name+std::string("'") 69 | << " " << boost::reflect::get_typename() 70 | << (M::is_const ? "const" : "") <(m_vtbl.*m); 72 | } 73 | */ 74 | template 75 | void operator()( const char* name ) const { 76 | typedef typename boost::function_types::result_type::type member_ref; 77 | typedef typename boost::remove_reference::type member; 78 | m_cli.methods[name] = cli_functor(m_vtbl.*m); 79 | /* 80 | typedef typename boost::remove_reference::type>::type R; 81 | std::cerr << std::setw(10) << std::setiosflags(std::ios::left) << std::string("'")+name+std::string("'") 82 | << " " << boost::reflect::get_typename() 83 | << (R::is_const ? "const" : "") <(m_vtbl.*m); 85 | */ 86 | } 87 | VTableType& m_vtbl; 88 | cli& m_cli; 89 | }; 90 | 91 | template 92 | struct cli_functor { 93 | cli_functor( Functor f ) 94 | :m_func(f){} 95 | 96 | typedef typename boost::remove_reference::type functor_type; 97 | 98 | template 99 | const T& wait_future( const boost::cmt::future& f ) { return f.wait(); } 100 | template 101 | const T& wait_future( const T& f ) { return f; } 102 | 103 | std::string operator()( const std::string& cli ) 104 | { 105 | typedef typename boost::fusion::traits::deduce_sequence::type param_type; 106 | boost::rpc::json::value v; 107 | boost::rpc::json::from_string(cli, v); 108 | param_type args; 109 | boost::rpc::json::io::unpack( v, args ); 110 | boost::rpc::json::value r; 111 | boost::rpc::json::io::pack( r, wait_future(m_func(args)) ); 112 | return r; 113 | } 114 | Functor m_func; 115 | }; 116 | std::map > methods; 117 | }; 118 | 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /examples/rpc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_IDL_RPC_HPP_ 2 | #define _BOOST_IDL_RPC_HPP_ 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace boost { namespace reflect { 24 | 25 | template 26 | struct item_serializer 27 | { 28 | item_serializer(Archive& ar):ar(ar) {} 29 | 30 | template 31 | void operator()(const T& o) const { 32 | ar << o; 33 | } 34 | Archive& ar; 35 | }; 36 | 37 | template 38 | Archive& serialize_fusion_vector(Archive& ar, const V& v) 39 | { 40 | boost::fusion::for_each(v, item_serializer(ar)); 41 | return ar; 42 | } 43 | 44 | template 45 | struct item_deserializer 46 | { 47 | item_deserializer(Archive& ar):ar(ar) {} 48 | 49 | template 50 | void operator()(T& o) const { 51 | ar >> o; 52 | } 53 | Archive& ar; 54 | }; 55 | 56 | template 57 | Archive& deserialize_fusion_vector(Archive& ar, V& v) 58 | { 59 | boost::fusion::for_each(v, item_deserializer(ar)); 60 | return ar; 61 | } 62 | 63 | 64 | 65 | /** 66 | * For each method on the interface, create a functor that will accept the 67 | * methods parameters, seralize them, and send them out the socket. 68 | */ 69 | template 70 | class rpc_client : public boost::reflect::visitor< rpc_client >, public reflect::any 71 | { 72 | public: 73 | rpc_client() 74 | :m_ios(),m_sock(m_ios) 75 | { 76 | start_visit(*this); 77 | } 78 | 79 | template 80 | bool accept( M& m, const char* name ) 81 | { 82 | m.m_delegate = rpc_functor(*this,name); 83 | return true; 84 | } 85 | boost::function& operator[]( const std::string& name ) 86 | { return methods[name]; } 87 | 88 | bool connect_to( const std::string& host, uint16_t port ) 89 | { 90 | m_sock.open(boost::asio::ip::udp::v4()); 91 | m_ep = boost::asio::ip::udp::endpoint( boost::asio::ip::address::from_string(host), port ); 92 | } 93 | 94 | std::string invoke( const char* name, const std::string& params ) 95 | { 96 | std::ostringstream os; 97 | { 98 | boost::archive::binary_oarchive oa(os); 99 | std::string n(name); 100 | oa << n; 101 | oa << params; 102 | } 103 | m_sock.send_to( boost::asio::buffer( os.str() ), m_ep ); 104 | boost::asio::ip::udp::endpoint rep; 105 | std::vector recv_buf(2048); 106 | size_t len = m_sock.receive_from( boost::asio::buffer(recv_buf), rep ); 107 | return std::string(&recv_buf.front(),len); 108 | } 109 | private: 110 | template 111 | struct rpc_functor 112 | { 113 | rpc_functor( rpc_client& c, const char* name ) 114 | :m_client(c),m_name(name){} 115 | 116 | ResultType operator()( const Seq& params ) 117 | { 118 | std::ostringstream os; 119 | { 120 | boost::archive::binary_oarchive oa(os); 121 | serialize_fusion_vector(oa, params); 122 | } 123 | ResultType ret_val; 124 | std::istringstream is(m_client.invoke( m_name, os.str() ) ); 125 | { 126 | boost::archive::binary_iarchive ia(is); 127 | ia >> ret_val; 128 | } 129 | return ret_val; 130 | } 131 | const char* m_name; 132 | rpc_client& m_client; 133 | }; 134 | boost::asio::ip::udp::endpoint m_ep; 135 | boost::asio::io_service m_ios; 136 | boost::asio::ip::udp::socket m_sock; 137 | std::map > methods; 138 | }; 139 | 140 | template 141 | class set_delegate_visitor< rpc_client > : 142 | public boost::reflect::visitor< set_delegate_visitor< rpc_client > > 143 | { 144 | public: 145 | set_delegate_visitor( rpc_client* self = 0) 146 | :m_self(self){} 147 | 148 | template 149 | bool accept( M& m, const char* name ) 150 | { 151 | M::get_member_on_type( m_self, m.m_delegate ); 152 | return true; 153 | } 154 | private: 155 | rpc_client* m_self; 156 | }; 157 | 158 | 159 | /** 160 | * Create a server socket that accepts new messages and then 161 | * unpacks the parameters and then invokes them on the object. 162 | */ 163 | template 164 | class rpc_server : public boost::reflect::visitor< rpc_server >, public reflect::any 165 | { 166 | public: 167 | template 168 | rpc_server( T v ) 169 | :reflect::any(v) 170 | { 171 | start_visit(*this); 172 | } 173 | 174 | void listen( uint16_t port ) 175 | { 176 | using namespace boost::asio::ip; 177 | boost::asio::io_service io_service; 178 | udp::socket socket( io_service, udp::endpoint(udp::v4(), port ) ); 179 | std::vector recv_buf(2048); 180 | for( ;; ) 181 | { 182 | udp::endpoint remote_ep; 183 | boost::system::error_code err; 184 | size_t bytes_recv = socket.receive_from( boost::asio::buffer(recv_buf), 185 | remote_ep, 0, err ); 186 | if( err && err != boost::asio::error::message_size ) 187 | throw boost::system::system_error(err); 188 | 189 | std::string buf(&recv_buf.front(),bytes_recv ); 190 | std::string method; 191 | std::string params; 192 | { 193 | std::istringstream iss( buf ); 194 | boost::archive::binary_iarchive ia(iss); 195 | ia >> method; 196 | ia >> params; 197 | } 198 | boost::system::error_code ignored_error; 199 | socket.send_to( boost::asio::buffer( methods[method](params) ), 200 | remote_ep, 0, ignored_error ); 201 | } 202 | } 203 | 204 | template 205 | bool accept( M& m, const char* name ) 206 | { 207 | methods[name] = rpc_functor(m); 208 | return true; 209 | } 210 | boost::function& operator[]( const std::string& name ) 211 | { return methods[name]; } 212 | 213 | private: 214 | template 215 | struct rpc_functor 216 | { 217 | rpc_functor( Functor f ) 218 | :m_func(f){} 219 | 220 | std::string operator()( const std::string& params ) 221 | { 222 | Seq paramv; 223 | std::istringstream is(params); 224 | { 225 | boost::archive::binary_iarchive ia(is); 226 | deserialize_fusion_vector(ia,paramv); 227 | } 228 | std::ostringstream os; 229 | { 230 | boost::archive::binary_oarchive oa(os); 231 | typename boost::remove_reference::type::result_type r = m_func(paramv); 232 | oa << r; 233 | } 234 | return os.str(); 235 | } 236 | Functor m_func; 237 | }; 238 | 239 | std::map > methods; 240 | }; 241 | 242 | } } // namespace boost::reflect 243 | 244 | #endif 245 | -------------------------------------------------------------------------------- /examples/rpc_client.cpp: -------------------------------------------------------------------------------- 1 | #include "calculator.hpp" 2 | #include "rpc.hpp" 3 | #include "cli.hpp" 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | /** 10 | * This is a simple RPC client that will connect to an 11 | * RPC server that implements the Calculator interface. 12 | * 13 | * In this case, the actual rpc interface is also wrapped in the 14 | * command line interface for Calculator. So the flow of control 15 | * becomes: 16 | * 17 | * User -> CLI -> RPC Client -> RPC Server -> Implementation 18 | * Display <- CLI <- RPC Client <- RPC Server <- 19 | * 20 | * 21 | */ 22 | int main( int argc, char** argv ) 23 | { 24 | if( argc <= 2 ) 25 | { 26 | std::cerr << "Usage: rpc_client IP PORT\n"; 27 | return -1; 28 | } 29 | using namespace boost; 30 | try { 31 | boost::shared_ptr > calc(new reflect::rpc_client()); 32 | calc->connect_to( argv[1], boost::lexical_cast(argv[2]) ); 33 | 34 | reflect::any s = calc; 35 | 36 | cli m_cli; 37 | m_cli.start_visit(s); 38 | 39 | std::string line; 40 | std::string cmd; 41 | std::string args; 42 | boost::posix_time::ptime start = boost::posix_time::microsec_clock::universal_time(); 43 | double sum = 0; 44 | int i = 0; 45 | for( i = 0; i < 100000; ++i ) 46 | { 47 | sum += calc->add(5); 48 | } 49 | boost::posix_time::ptime end = boost::posix_time::microsec_clock::universal_time(); 50 | uint64_t us = (end-start).total_microseconds(); 51 | std::cerr << i << " add(5) took " << us << "us " << double(i) / (us/1000000.0) << "invoke/sec\n"; 52 | 53 | while( true ) 54 | { 55 | std::cerr << "Enter Method: "; 56 | std::getline( std::cin, line ); 57 | cmd = line.substr( 0, line.find('(') ); 58 | args = line.substr( cmd.size(), line.size() ); 59 | std::cerr << m_cli[cmd](args) << std::endl; 60 | } 61 | 62 | } catch ( const boost::exception& e ) 63 | { 64 | std::cerr << boost::diagnostic_information(e) << std::endl; 65 | } 66 | return 0; 67 | } 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/rpc_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "calculator.hpp" 3 | #include "rpc.hpp" 4 | #include 5 | 6 | class CalculatorServer 7 | { 8 | public: 9 | CalculatorServer():m_result(0){} 10 | 11 | std::string name()const { return "CalculatorServer"; } 12 | int exit() { ::exit(0); } 13 | double add( double v ) { return m_result += v; } 14 | double sub( double v ) { return m_result -= v; } 15 | double mult( double v ) { return m_result *= v; } 16 | double div( double v ) { return m_result /= v; } 17 | double add2( double v, double v2 ) { return m_result += v + v2; } 18 | 19 | double result()const { return m_result; } 20 | 21 | private: 22 | double m_result; 23 | }; 24 | 25 | int main( int argc, char** argv ) 26 | { 27 | if( argc <= 1 ) 28 | { 29 | std::cerr << "Usage: rpc_server PORT\n"; 30 | return -1; 31 | } 32 | using namespace boost; 33 | try { 34 | boost::shared_ptr calc(new CalculatorServer()); 35 | reflect::rpc_server server( calc ); 36 | server.listen( lexical_cast(argv[1]) ); 37 | } catch ( const boost::exception& e ) 38 | { 39 | std::cerr << boost::diagnostic_information(e) << std::endl; 40 | } 41 | return 0; 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /examples/signal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cli.hpp" 3 | #include 4 | 5 | struct Service 6 | { 7 | std::string name()const; 8 | int exit(); 9 | }; 10 | struct Calculator : Service 11 | { 12 | double add( double v ); 13 | double add2( double v, double v2 ); 14 | double sub( double v ); 15 | double mult( double v ); 16 | double div( double v ); 17 | double result()const; 18 | boost::signal got_result; 19 | }; 20 | 21 | BOOST_REFLECT_ANY( Service, (name)(exit) ) 22 | BOOST_REFLECT_ANY_DERIVED( Calculator, (Service), (add)(add2)(sub)(mult)(div)(result)(got_result) ) 23 | 24 | class CalculatorService 25 | { 26 | public: 27 | CalculatorService():m_result(0){} 28 | 29 | std::string name()const { return "CalculatorService"; } 30 | int exit() { ::exit(0); } 31 | double add( double v ) { got_result(m_result += v); return m_result;} 32 | double sub( double v ) { got_result(m_result -= v); return m_result; } 33 | double mult( double v ) { got_result(m_result *= v); return m_result; } 34 | double div( double v ) { got_result(m_result /= v); return m_result; } 35 | double add2( double v, double v2 ) { got_result(m_result += v + v2); return m_result; } 36 | 37 | double result()const { return m_result; } 38 | 39 | boost::signal got_result; 40 | private: 41 | double m_result; 42 | }; 43 | 44 | void print( double r ) { 45 | std::cerr<<"got result "<got_result(5); 55 | if( se->got_result.empty() ) 56 | std::cerr<<"EMPTY!\n"; 57 | se->got_result.connect(&print); 58 | if( !se->got_result.empty() ) 59 | std::cerr<<"NOT EMPTY!\n"; 60 | se->got_result(5); 61 | 62 | 63 | boost::reflect::any_ptr s( se ); 64 | s->got_result.connect(&print2); 65 | se->got_result(1234); 66 | printf( "Result: %f\n", s->result() ); 67 | 68 | cli m_cli(s); 69 | 70 | std::string line; 71 | std::string cmd; 72 | std::string args; 73 | 74 | while( true ) 75 | { 76 | std::cerr << "Enter Method: "; 77 | std::getline( std::cin, line ); 78 | cmd = line.substr( 0, line.find('(') ); 79 | args = line.substr( cmd.size(), line.size() ); 80 | std::cerr << m_cli[cmd](args) << std::endl; 81 | } 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /examples/simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cli.hpp" 3 | #include 4 | 5 | struct Service 6 | { 7 | std::string name()const; 8 | int exit(); 9 | }; 10 | struct Calculator : Service 11 | { 12 | void add( double v ); 13 | double add2( double v, double v2 ); 14 | double sub( double v ); 15 | double mult( double v ); 16 | double div( double v ); 17 | double result()const; 18 | }; 19 | 20 | BOOST_REFLECT_ANY( Service, (name)(exit) ) 21 | BOOST_REFLECT_ANY_DERIVED( Calculator, (Service), (add)(add2)(sub)(mult)(div)(result) ) 22 | 23 | class CalculatorService 24 | { 25 | public: 26 | CalculatorService():m_result(0){} 27 | 28 | std::string name()const { return "CalculatorService"; } 29 | int exit() { ::exit(0); } 30 | void add( double v ) { m_result += v; } 31 | double sub( double v ) { return m_result -= v; } 32 | double mult( double v ) { return m_result *= v; } 33 | double div( double v ) { return m_result /= v; } 34 | double add2( double v, double v2 ) { return m_result += v + v2; } 35 | 36 | double result()const { return m_result; } 37 | 38 | private: 39 | double m_result; 40 | }; 41 | 42 | 43 | int main( int argc, char** argv ) 44 | { 45 | boost::reflect::any_ptr s( new CalculatorService() ); 46 | printf( "Result: %f\n", s->result() ); 47 | 48 | cli m_cli(s); 49 | 50 | std::string line; 51 | std::string cmd; 52 | std::string args; 53 | 54 | while( true ) 55 | { 56 | std::cerr << "Enter Method: "; 57 | std::getline( std::cin, line ); 58 | cmd = line.substr( 0, line.find('(') ); 59 | args = line.substr( cmd.size(), line.size() ); 60 | std::cerr << m_cli[cmd](args) << std::endl; 61 | } 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /examples/value_test.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct test { 9 | test( int _a, std::string _b ) 10 | :a(_a),b(_b){ } 11 | test():a(0),b("default"){ } 12 | 13 | test( const test& c ) 14 | :a(c.a),b(c.b){ } 15 | 16 | ~test() { } 17 | 18 | int a; 19 | std::string b; 20 | }; 21 | BOOST_REFLECT( test, (a)(b) ) 22 | 23 | void test_cr( const test& t ) { 24 | boost::reflect::value_cref r(t); 25 | slog("%1%", r["a"].get());// == int(5) ); 26 | slog("%1%", r["b"].get() ); 27 | } 28 | void test_rv( const boost::reflect::value_cref& v ) { 29 | slog( "b:%1%", v.ptr()->b ); 30 | test_cr(v.get()); 31 | } 32 | 33 | 34 | using namespace boost::reflect; 35 | 36 | 37 | void test_visitor( value_ref& v ) { 38 | std::cout<<"as str: "<()<()<(55); // does not compile as expected, generates assert 47 | try { 48 | std::cout<<"as str: 55 ?= "<()<()<()<()<(5); // does not compile as expected, generates assert 66 | } 67 | 68 | void test_ref_passed_to_cref( const value_cref& v ) { 69 | slog( "ref passed to cref..." ); 70 | BOOST_ASSERT( v["a"] == int(6) ); 71 | BOOST_ASSERT( v["b"] == std::string("good bye\n") ); 72 | slog( "passed const test\n" ); 73 | 74 | value_cref v2; 75 | 76 | v2 = v; 77 | 78 | test_const_visitor(v2); 79 | } 80 | 81 | void test_value_ref() { 82 | test t; 83 | t.a = 5; 84 | t.b = "hello world"; 85 | boost::reflect::value_ref r(t); 86 | test_const_visitor(r); 87 | test_visitor(r); 88 | slog("passed "); 89 | BOOST_ASSERT( r["a"] == int(5) ); 90 | BOOST_ASSERT( r["b"] == std::string("hello world") ); 91 | slog("passed compare check"); 92 | r["a"] = int(6); 93 | r["b"] = std::string( "good bye\n" ); 94 | BOOST_ASSERT( r["a"] == int(6) ); 95 | BOOST_ASSERT( r["b"] == std::string("good bye\n") ); 96 | slog( "passed assign\n" ); 97 | 98 | slog( "a: %1% b: %2%", r["a"].get(), r["b"].get() ); 99 | 100 | slog("calling tesT_ref_passed_to_cref" ); 101 | test_ref_passed_to_cref(r); 102 | } 103 | 104 | 105 | void test_value_cref() { 106 | test t; 107 | t.a = 5; 108 | t.b = "hello world"; 109 | boost::reflect::value_cref r(t); 110 | BOOST_ASSERT( r["a"] == int(5) ); 111 | BOOST_ASSERT( r["b"] == std::string("hello world") ); 112 | BOOST_ASSERT( !r["d"] ); 113 | BOOST_ASSERT( !!r["a"] ); 114 | 115 | //r["a"] = int(6); // this should not compile 116 | //r["b"] = std::string( "good bye\n" ); // this should not compile 117 | } 118 | 119 | 120 | int main( int argc, char** argv ) { 121 | try { 122 | test_value_ref(); 123 | test_value_cref(); 124 | } catch( const boost::exception& e ) { 125 | elog( "%1%", boost::diagnostic_information(e) ); 126 | } catch( const std::exception& e ) { 127 | elog( "%1%", boost::diagnostic_information(e) ); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE headers boost/*.* ) 2 | boost_add_headers(${headers}) 3 | -------------------------------------------------------------------------------- /include/boost/reflect/any_ptr.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_ANY_PTR_HPP 2 | #define _BOOST_REFLECT_ANY_PTR_HPP 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace boost { namespace reflect { 9 | 10 | /** 11 | * @class any_ptr 12 | * @brief Behaves like a smart pointer that can handle any type with the same interface. 13 | * 14 | * If constructed from a shared pointer, then a copy of the shared pointer will go with 15 | * every any_ptr. If constructed from a regular pointer, then the pointer must be valid 16 | * for the life of all copies of the any_ptr. 17 | * 18 | */ 19 | template 20 | class any_ptr { 21 | public: 22 | typedef boost::reflect::vtable vtable_type; 23 | typedef InterfaceType interface_type; 24 | typedef InterfaceDelegate delegate_type; 25 | 26 | any_ptr() 27 | :m_vtable(boost::make_shared()) {} 28 | 29 | operator bool()const { return m_vtable; } 30 | bool operator!()const { return !m_vtable; } 31 | 32 | template 33 | any_ptr( T* v ) 34 | :m_ptr( boost::make_shared(v) ),m_vtable(boost::make_shared()) { 35 | InterfaceDelegate::set_vtable(*m_vtable,*v); 36 | } 37 | template 38 | any_ptr( const boost::shared_ptr& v ) 39 | :m_ptr(boost::make_shared(v)),m_vtable(boost::make_shared()) { 40 | InterfaceDelegate::set_vtable(*m_vtable,*v); 41 | } 42 | 43 | /** 44 | * @brief constructs an any_ptr from another any_ptr with compatible interface. 45 | */ 46 | template 47 | any_ptr( const any_ptr& p ) 48 | :m_ptr(p),m_vtable(boost::make_shared()) { 49 | InterfaceDelegate::set_vtable( *m_vtable, *boost::any_cast&>(m_ptr) ); 50 | } 51 | 52 | const vtable_type& operator*()const { return *m_vtable; } 53 | vtable_type& operator*() { return *m_vtable; } 54 | 55 | const vtable_type* operator->()const { return m_vtable.get(); } 56 | vtable_type* operator->() { return m_vtable.get(); } 57 | 58 | protected: 59 | boost::shared_ptr m_ptr; 60 | boost::shared_ptr m_vtable; 61 | }; 62 | /** 63 | * @brief Helper function to enable automatic type deduction. 64 | * 65 | * Calls visitor with each member of the vtable of the any_ptr. 66 | */ 67 | template 68 | void visit( const any_ptr& aptr, Visitor v ) { 69 | boost::reflect::vtable_reflector::visit( &*aptr, v ); 70 | } 71 | 72 | } } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/get_field.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_DETAIL_GET_FIELD_HPP 2 | #define _BOOST_REFLECT_DETAIL_GET_FIELD_HPP 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace boost { namespace reflect { 15 | 16 | namespace detail { struct get_field_method; } 17 | 18 | typedef boost::unordered_map field_map_type; 19 | 20 | template 21 | value_ref get_field( const std::string& n, T& v ); 22 | 23 | template 24 | value_cref get_field( const std::string& n, const T& v ); 25 | 26 | namespace detail { 27 | struct get_field_method { 28 | public: 29 | get_field_method( const char* n ):m_name(n){} 30 | virtual value_ref operator()( void* f )const = 0; 31 | virtual value_cref operator()( const void* f )const = 0; 32 | const char* name()const { return m_name; } 33 | private: 34 | const char* m_name; 35 | }; 36 | 37 | template 38 | struct get_field_method_impl : get_field_method { 39 | get_field_method_impl( const char* n ):get_field_method(n){} 40 | virtual value_ref operator()( void* f )const { 41 | typedef typename mpl::at_c< function_types::components >,1 >::type C; 42 | return value_ref((((C*)f)->*p)); 43 | } 44 | virtual value_cref operator()( const void* f )const { 45 | typedef typename mpl::at_c< function_types::components >,1 >::type C; 46 | return value_cref((((const C*)f)->*p)); 47 | } 48 | }; 49 | 50 | class get_field_visitor { 51 | public: 52 | get_field_visitor( field_map_type& _field_map ) 53 | :field_map(_field_map){} 54 | 55 | template 56 | inline void operator()( const char* name )const { 57 | static get_field_method_impl gfm(name); 58 | field_map[name] = &gfm; 59 | } 60 | field_map_type& field_map; 61 | }; 62 | 63 | /** 64 | * Atomicly creates a field map, deletes old one if there 65 | * was a race condition on creating it. 66 | */ 67 | template 68 | static field_map_type* create_field_map() { 69 | static boost::atomic fm(0); 70 | field_map_type* n = new field_map_type(); 71 | boost::reflect::reflector::visit( get_field_visitor(*n) ); 72 | delete fm.exchange(n,boost::memory_order_consume); 73 | return fm; 74 | } 75 | } // namespace detail 76 | 77 | 78 | /** 79 | * returns the singlton field map for T 80 | */ 81 | template 82 | const field_map_type& get_field_map() { 83 | static field_map_type* fm = detail::create_field_map(); 84 | return *fm; 85 | } 86 | 87 | template 88 | bool has_field( const std::string& n ) { 89 | field_map_type::const_iterator itr = get_field_map().find(n); 90 | return itr != get_field_map().end(); 91 | } 92 | template 93 | value_ref get_field( const std::string& n, T& v ) { 94 | field_map_type::const_iterator itr = get_field_map().find(n); 95 | if( itr != get_field_map().end() ) 96 | return (*itr->second)(&v); 97 | BOOST_THROW_EXCEPTION( unknown_field() << err_msg(n+": '"+n+"'") ); 98 | } 99 | template 100 | value_cref get_field( const std::string& n, const T& v ) { 101 | field_map_type::const_iterator itr = get_field_map().find(n); 102 | if( itr != get_field_map().end() ) 103 | return (*itr->second)(&v); 104 | BOOST_THROW_EXCEPTION( unknown_field() << err_msg(n+": '"+n+"'") ); 105 | } 106 | 107 | template 108 | class iterator_impl; 109 | 110 | template 111 | class const_iterator_impl : public detail::const_iterator_impl_base { 112 | public: 113 | const T& val; 114 | field_map_type::const_iterator itr; 115 | 116 | const_iterator_impl( const T& _val, const field_map_type::const_iterator& i ) 117 | :val(_val),itr(i){} 118 | 119 | const_iterator_impl( const const_iterator_impl& c ) 120 | :val(c.val),itr(c.itr){} 121 | 122 | virtual std::string key()const { return itr->first; } 123 | virtual value_ref value()const { BOOST_THROW_EXCEPTION( bad_value_cast() );} 124 | virtual value_cref const_value()const { return (*itr->second)(&val); } 125 | virtual const_iterator_impl_base* const_clone()const { return new const_iterator_impl(val,itr); } 126 | virtual const char* type()const { return get_typename >(); } 127 | 128 | virtual void next() { ++itr; } 129 | virtual bool equals( const const_iterator_impl_base* other )const { 130 | if( other == 0 ) 131 | return itr == get_field_map().end(); 132 | 133 | if( type() == other->type() ) { 134 | return itr == static_cast*>(other)->itr; 135 | &val == &static_cast*>(other)->val; 136 | } 137 | } 138 | }; 139 | template 140 | class iterator_impl : public detail::iterator_impl_base { 141 | public: 142 | T& val; 143 | field_map_type::const_iterator itr; 144 | 145 | iterator_impl( T& _val, const field_map_type::const_iterator& i ) 146 | :val(_val),itr(i){} 147 | 148 | iterator_impl( const iterator_impl& c ) 149 | :val(c.val),itr(c.itr){} 150 | 151 | virtual std::string key()const { return itr->first; } 152 | virtual value_ref value()const { return (*itr->second)(&val); } 153 | virtual value_cref const_value()const { return (*itr->second)(&val); } 154 | virtual iterator_impl_base* clone()const { return new iterator_impl(val,itr); } 155 | virtual const_iterator_impl_base* const_clone()const { return new const_iterator_impl(val,itr); } 156 | virtual const char* type()const { return get_typename >(); } 157 | 158 | virtual void next() { ++itr; } 159 | virtual bool equals( const const_iterator_impl_base* other )const { 160 | if( other == 0 ) 161 | return itr == get_field_map().end(); 162 | 163 | if( type() == other->type() ) { 164 | return itr == static_cast*>(other)->itr; 165 | &val == &static_cast*>(other)->val; 166 | } 167 | } 168 | }; 169 | 170 | 171 | } } // boost::reflect 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/iterator.ipp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_ITERATOR_IPP_ 2 | #define _BOOST_REFLECT_ITERATOR_IPP_ 3 | #include 4 | #include 5 | 6 | namespace boost { namespace reflect { 7 | 8 | std::string iterator::key()const { return itr->key(); } 9 | value_ref iterator::value()const { return itr->value(); } 10 | 11 | // 0 == end 12 | iterator::iterator( detail::iterator_impl_base* i ) 13 | :itr(i){} 14 | 15 | iterator::iterator( const iterator& i ) 16 | :itr(i.itr->clone()){} 17 | 18 | iterator::iterator( iterator&& i ) 19 | :itr(i.itr) { i.itr = 0; } 20 | 21 | iterator::~iterator(){ delete itr; } 22 | 23 | iterator& iterator::operator=( const iterator& i ) { 24 | if( this != &i ) { 25 | delete itr; 26 | itr = i.itr->clone(); 27 | } 28 | return *this; 29 | } 30 | 31 | iterator& iterator::operator++(int) { itr->next(); return *this; } 32 | iterator& iterator::operator++() { itr->next(); return *this; } 33 | 34 | bool iterator::operator == ( const iterator& i )const { 35 | if( itr == i.itr ) return true; 36 | if( itr == 0 ) return i.itr->equals(itr); 37 | return itr->equals(i.itr); 38 | } 39 | 40 | 41 | /** 42 | * 43 | * 44 | * const_iterator 45 | * 46 | * 47 | */ 48 | inline const_iterator::const_iterator( const const_iterator& i ) 49 | :itr(i.itr->const_clone()){} 50 | inline const_iterator::const_iterator( const iterator& i ) 51 | :itr(i.itr->clone()){} 52 | 53 | inline const_iterator::const_iterator( const_iterator&& i ) 54 | :itr(i.itr) { i.itr = 0; } 55 | inline const_iterator::const_iterator( detail::const_iterator_impl_base* b ) 56 | :itr( b ){} 57 | 58 | inline const_iterator::~const_iterator(){ delete itr; } 59 | inline std::string const_iterator::key()const { return itr->key(); } 60 | inline value_cref const_iterator::value()const { return itr->const_value(); } 61 | 62 | inline const_iterator& const_iterator::operator++(int) { itr->next(); return *this; } 63 | inline const_iterator& const_iterator::operator++() { itr->next(); return *this; } 64 | 65 | inline bool const_iterator::operator == ( const const_iterator& i )const { 66 | if( itr == i.itr ) return true; 67 | if( itr == 0 ) return i.itr->equals(itr); 68 | return itr->equals(i.itr); 69 | } 70 | inline bool const_iterator::operator != ( const const_iterator& i )const { 71 | return !(*this == i); 72 | } 73 | 74 | } } 75 | #endif // _BOOST_REFLECT_ITERATOR_IPP_ 76 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/iterator_impl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __BOOST_REFLECT_DETAIL_ITERATOR_IMPL_HPP_ 2 | #define __BOOST_REFLECT_DETAIL_ITERATOR_IMPL_HPP_ 3 | 4 | #include 5 | #include 6 | 7 | namespace boost { namespace reflect { namespace detail { 8 | 9 | class const_iterator_impl_base { 10 | public: 11 | virtual ~const_iterator_impl_base(){} 12 | virtual std::string key()const = 0; 13 | virtual value_cref const_value()const = 0; 14 | virtual const_iterator_impl_base* const_clone()const = 0; 15 | 16 | virtual void next() = 0; 17 | virtual bool equals( const const_iterator_impl_base* other )const = 0; 18 | virtual const char* type()const = 0; 19 | }; 20 | 21 | class iterator_impl_base : public const_iterator_impl_base { 22 | public: 23 | virtual value_ref value()const = 0; 24 | virtual iterator_impl_base* clone()const = 0; 25 | }; 26 | 27 | template 28 | class const_vector_iterator_impl; 29 | 30 | template 31 | class vector_iterator_impl : public iterator_impl_base { 32 | public: 33 | typename std::vector::iterator itr; 34 | std::vector& vec; 35 | vector_iterator_impl( std::vector& v, const typename std::vector::iterator i ):vec(v),itr(i){} 36 | 37 | virtual std::string key()const { return boost::lexical_cast(itr-vec.begin()); } 38 | virtual value_ref value()const { return *itr; } 39 | virtual value_cref const_value()const { return *itr; } 40 | virtual const_iterator_impl_base* const_clone()const { return new const_vector_iterator_impl(vec,itr); } 41 | virtual iterator_impl_base* clone()const { return new vector_iterator_impl(vec,itr); } 42 | 43 | virtual void next() { ++itr; } 44 | virtual bool equals( const const_iterator_impl_base* other )const{ 45 | if( other == 0 ) 46 | return itr == vec.end(); 47 | 48 | if( type() == other->type() ) { 49 | return itr == static_cast*>(other)->itr; 50 | } 51 | } 52 | virtual const char* type()const { return get_typename(); } 53 | }; 54 | 55 | template 56 | class const_vector_iterator_impl : public const_iterator_impl_base { 57 | public: 58 | typename std::vector::const_iterator itr; 59 | const std::vector& vec; 60 | const_vector_iterator_impl( const std::vector& v, const typename std::vector::const_iterator& i ):vec(v),itr(i){} 61 | 62 | virtual std::string key()const { return boost::lexical_cast(itr-vec.begin()); } 63 | virtual value_cref const_value()const { return *itr; } 64 | virtual const_iterator_impl_base* const_clone()const { return new const_vector_iterator_impl(vec,itr); } 65 | 66 | virtual void next() { ++itr; } 67 | virtual bool equals( const const_iterator_impl_base* other )const{ 68 | if( other == 0 ) 69 | return itr == vec.end(); 70 | 71 | if( type() == other->type() ) { 72 | return itr == static_cast*>(other)->itr; 73 | } 74 | } 75 | virtual const char* type()const { return get_typename(); } 76 | }; 77 | 78 | template 79 | class const_map_iterator_impl; 80 | 81 | template 82 | class map_iterator_impl : public iterator_impl_base { 83 | public: 84 | typename std::map::iterator itr; 85 | std::map& vec; 86 | map_iterator_impl( std::map& v, const typename std::map::iterator i ):vec(v),itr(i){} 87 | 88 | virtual std::string key()const { return boost::lexical_cast(itr->first); } 89 | virtual value_ref value()const { return itr->second; } 90 | virtual value_cref const_value()const { return itr->second; } 91 | virtual const_iterator_impl_base* const_clone()const { return new const_map_iterator_impl(vec,itr); } 92 | virtual iterator_impl_base* clone()const { return new map_iterator_impl(vec,itr); } 93 | 94 | virtual void next() { ++itr; } 95 | virtual bool equals( const const_iterator_impl_base* other )const{ 96 | if( other == 0 ) 97 | return itr == vec.end(); 98 | 99 | if( type() == other->type() ) { 100 | return itr == static_cast*>(other)->itr; 101 | } 102 | } 103 | virtual const char* type()const { return get_typename(); } 104 | }; 105 | 106 | template 107 | class const_map_iterator_impl : public const_iterator_impl_base { 108 | public: 109 | typename std::map::const_iterator itr; 110 | const std::map& vec; 111 | const_map_iterator_impl( const std::map& v, const typename std::map::const_iterator& i ):vec(v),itr(i){} 112 | 113 | virtual std::string key()const { return boost::lexical_cast(itr->first); } 114 | virtual value_cref const_value()const { return itr->second; } 115 | virtual const_iterator_impl_base* const_clone()const { return new const_map_iterator_impl(vec,itr); } 116 | 117 | virtual void next() { ++itr; } 118 | virtual bool equals( const const_iterator_impl_base* other )const{ 119 | if( other == 0 ) 120 | return itr == vec.end(); 121 | 122 | if( type() == other->type() ) { 123 | return itr == static_cast*>(other)->itr; 124 | } 125 | } 126 | virtual const char* type()const { return get_typename(); } 127 | }; 128 | 129 | 130 | } } } 131 | 132 | 133 | 134 | #endif // __BOOST_REFLECT_DETAIL_ITERATOR_IMPL_HPP_ 135 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/place_holder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_DETAIL_PLACE_HOLDER_HPP_ 2 | #define _BOOST_REFLECT_DETAIL_PLACE_HOLDER_HPP_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace boost { namespace reflect { namespace detail { 14 | 15 | 16 | struct place_holder { 17 | virtual ~place_holder(){} 18 | virtual const char* type()const { return 0; } 19 | virtual void* ptr() { return 0; } 20 | virtual const void* ptr()const { return 0; } 21 | virtual place_holder* clone( char* place = 0 )const { 22 | if( place ) return new(place)place_holder(); 23 | return new place_holder(); 24 | } 25 | virtual value call( const std::vector& params )const { return value(); } 26 | virtual value call( const std::vector& params ) { return value(); } 27 | 28 | virtual void visit( read_value_visitor&& v )const { v(); } 29 | virtual void visit( write_value_visitor&& v ) { v(); } 30 | 31 | virtual iterator_impl_base* begin() { return 0; } 32 | virtual const_iterator_impl_base* begin()const { return 0; } 33 | virtual size_t size()const { return 0; } 34 | virtual bool is_array()const { return 0; } 35 | 36 | virtual value copy()const { BOOST_THROW_EXCEPTION(bad_value_cast()); } 37 | virtual value_cref cref()const { BOOST_THROW_EXCEPTION(bad_value_cast()); } 38 | virtual bool has_field( const std::string& f )const { return false; } 39 | virtual value_ref get_field( const std::string& f ) { BOOST_THROW_EXCEPTION(bad_value_cast()); } 40 | virtual value_cref get_field( const std::string& f )const { BOOST_THROW_EXCEPTION(bad_value_cast()); } 41 | virtual value_ref get_field( uint64_t idx ) { BOOST_THROW_EXCEPTION(bad_value_cast()); } 42 | virtual value_cref get_field( uint64_t idx )const { BOOST_THROW_EXCEPTION(bad_value_cast()); } 43 | }; 44 | 45 | 46 | template 47 | struct place_holder_impl : place_holder { 48 | place_holder_impl( const T& v ):val(new T(v)){} 49 | place_holder_impl( T&& v ):val(new T(v)){} 50 | ~place_holder_impl() { delete val; } 51 | 52 | virtual size_t size()const { return get_field_map().size(); } 53 | virtual const char* type()const { return get_typename(); } 54 | virtual void* ptr() { return val; } 55 | virtual const void* ptr()const { return val; } 56 | virtual place_holder* clone( char* place = 0 )const { 57 | if( place ) return new (place) place_holder_impl(*val); 58 | return new place_holder_impl(*val); 59 | } 60 | 61 | virtual void visit( read_value_visitor&& v )const { v(*val); } 62 | virtual void visit( write_value_visitor&& v ) { v(*val); } 63 | 64 | virtual value_cref cref()const { return *val; } 65 | virtual value copy()const { return *val; } 66 | virtual bool has_field( const std::string& f )const { return reflect::has_field(f); } 67 | virtual value_ref get_field( const std::string& f ){ 68 | return reflect::get_field(f,*val); 69 | } 70 | virtual value_cref get_field( const std::string& f )const { 71 | return reflect::get_field(f,*val); 72 | } 73 | const T& get_val()const { return *val; } 74 | T& get_val() { return *val; } 75 | 76 | virtual iterator_impl_base* begin() { return new iterator_impl(get_val(), get_field_map().begin()); } 77 | virtual const_iterator_impl_base* begin()const { return new const_iterator_impl(get_val(), get_field_map().begin()); } 78 | 79 | T* val; 80 | }; 81 | 82 | template 83 | struct place_holder_impl : place_holder { 84 | place_holder_impl( T&& v ):val(std::forward(v)){} 85 | place_holder_impl( const T& v ):val(v){} 86 | 87 | virtual size_t size()const { return get_field_map().size(); } 88 | virtual const char* type()const { return get_typename(); } 89 | virtual void* ptr() { return &val; } 90 | virtual const void* ptr()const { return &val; } 91 | virtual place_holder* clone( char* place = 0 )const { 92 | if( place ) return new (place) place_holder_impl(val); 93 | return new place_holder_impl(val); 94 | } 95 | 96 | virtual void visit( read_value_visitor&& v )const { v(val); } 97 | virtual void visit( write_value_visitor&& v ) { v(val); } 98 | 99 | virtual value copy()const { return val; } 100 | virtual bool has_field( const std::string& f )const { return reflect::has_field(f); } 101 | virtual value_ref get_field( const std::string& f ){ 102 | return reflect::get_field(f,val); 103 | } 104 | virtual value_cref get_field( const std::string& f )const { 105 | return reflect::get_field(f,val); 106 | } 107 | 108 | virtual iterator_impl_base* begin() { return new iterator_impl(val, get_field_map().begin()); } 109 | virtual const_iterator_impl_base* begin()const { return new const_iterator_impl(val, get_field_map().begin()); } 110 | 111 | const T& get_val()const { return val; } 112 | T& get_val() { return val; } 113 | T val; 114 | }; 115 | 116 | template 117 | struct place_holder_impl : place_holder { 118 | place_holder_impl( T& v ):val(v){} 119 | 120 | virtual size_t size()const { return get_field_map().size(); } 121 | virtual const char* type()const { return get_typename(); } 122 | virtual void* ptr() { return &val; } 123 | virtual const void* ptr()const { return &val; } 124 | virtual place_holder* clone( char* place = 0 )const { 125 | if( place ) return new (place) place_holder_impl(val); 126 | return new place_holder_impl(val); 127 | } 128 | 129 | virtual void visit( read_value_visitor&& v )const { v(val); } 130 | virtual void visit( write_value_visitor&& v ) { v(val); } 131 | 132 | virtual value_cref cref()const { return val; } 133 | virtual value copy()const { return val; } 134 | virtual bool has_field( const std::string& f )const { return reflect::has_field(f); } 135 | virtual value_ref get_field( const std::string& f ) { 136 | return reflect::get_field(f,val); 137 | } 138 | virtual value_cref get_field( const std::string& f )const{ 139 | return reflect::get_field(f,val); 140 | } 141 | 142 | virtual iterator_impl_base* begin() { return new iterator_impl(val, get_field_map().begin()); } 143 | virtual const_iterator_impl_base* begin()const { return new const_iterator_impl(val, get_field_map().begin()); } 144 | 145 | const T& get_val()const { return val; } 146 | T& get_val() { return val; } 147 | T& val; 148 | }; 149 | 150 | template 151 | struct place_holder_impl : place_holder { 152 | place_holder_impl( const T& v ):val(v){} 153 | 154 | virtual size_t size()const { return get_field_map().size(); } 155 | virtual const char* type()const { return get_typename(); } 156 | virtual void* ptr() { return 0; } 157 | virtual const void* ptr()const { return &val; } 158 | virtual place_holder* clone( char* place = 0 )const { 159 | if( place ) return new (place) place_holder_impl(val); 160 | return new place_holder_impl(val); 161 | } 162 | 163 | virtual void visit( read_value_visitor&& v )const { v(val); } 164 | virtual void visit( write_value_visitor&& v ) { v(); } 165 | 166 | virtual value_cref cref()const { return val; } 167 | virtual value copy()const { return val; } 168 | virtual bool has_field( const std::string& f )const { return reflect::has_field(f); } 169 | virtual value_ref get_field( const std::string& f ) { 170 | BOOST_THROW_EXCEPTION(bad_value_cast()); 171 | } 172 | virtual value_cref get_field( const std::string& f )const { 173 | return reflect::get_field(f,val); 174 | } 175 | virtual iterator_impl_base* begin() { BOOST_THROW_EXCEPTION( bad_value_cast() ); return 0; } 176 | virtual const_iterator_impl_base* begin()const { return new const_iterator_impl(val, get_field_map().begin()); } 177 | 178 | const T& get_val()const { return val; } 179 | 180 | const T& val; 181 | }; 182 | 183 | 184 | template 185 | struct place_holder_array: public Base { 186 | place_holder_array(){} 187 | place_holder_array( T& v ):Base(v){} 188 | place_holder_array( const T& v ):Base(v){} 189 | place_holder_array( T&& v ):Base(std::forward(v)){} 190 | virtual bool is_array()const { return true; } 191 | virtual size_t size()const { return this->get_val().size(); } 192 | virtual bool has_field( const std::string& f )const { 193 | try { 194 | uint64_t idx = boost::lexical_cast(f); 195 | return idx < size(); 196 | } catch ( ... ) { return false; } // bad lexical cast 197 | } 198 | virtual value_ref get_field( const std::string& f ) { 199 | uint64_t idx = boost::lexical_cast(f); 200 | return this->get_val()[idx]; 201 | } 202 | virtual value_cref get_field( const std::string& f )const{ 203 | uint64_t idx = boost::lexical_cast(f); 204 | return this->get_val()[idx]; 205 | } 206 | virtual value_ref get_field( uint64_t idx ) { return this->get_val()[idx]; } 207 | virtual value_cref get_field( uint64_t idx )const { return this->get_val()[idx]; } 208 | virtual iterator_impl_base* begin() { return new vector_iterator_impl( this->get_val(), this->get_val().begin() ); } 209 | virtual const_iterator_impl_base* begin()const { return new const_vector_iterator_impl( this->get_val(), this->get_val().begin() ); } 210 | }; 211 | 212 | 213 | template 214 | struct place_holder_const_array: public Base { 215 | place_holder_const_array( const T& v ):Base(v){} 216 | virtual bool is_array()const { return true; } 217 | virtual size_t size()const { return this->get_val().size(); } 218 | virtual bool has_field( const std::string& f )const { 219 | try { 220 | uint64_t idx = boost::lexical_cast(f); 221 | return idx < size(); 222 | } catch ( ... ) { return false; } // bad lexical cast 223 | } 224 | virtual value_cref get_field( const std::string& f )const{ 225 | uint64_t idx = boost::lexical_cast(f); 226 | return this->get_val()[idx]; 227 | } 228 | virtual value_cref get_field( uint64_t idx )const { return this->get_val()[idx]; } 229 | 230 | virtual iterator_impl_base* begin() { return 0; } 231 | virtual const_iterator_impl_base* begin()const { return new const_vector_iterator_impl( this->get_val(), this->get_val().begin() ); } 232 | }; 233 | 234 | 235 | 236 | template 237 | struct place_holder_map: public Base { 238 | place_holder_map( std::map& v ):Base(v){} 239 | place_holder_map( const std::map& v ):Base(v){} 240 | place_holder_map( std::map&& v ):Base(std::forward >(v) ){} 241 | virtual bool is_array()const { return false; } 242 | virtual size_t size()const { return this->get_val().size(); } 243 | virtual bool has_field( const std::string& f )const { 244 | try { 245 | return this->get_val().find(boost::lexical_cast(f)) != this->get_val().end(); 246 | } catch ( ... ) { return false; } 247 | } 248 | virtual value_ref get_field( const std::string& f ) { 249 | return this->get_val()[boost::lexical_cast(f)]; 250 | } 251 | virtual value_cref get_field( const std::string& f )const{ 252 | typename std::map::const_iterator itr = this->get_val().find(boost::lexical_cast(f)); 253 | if( itr != this->get_val().end() ) 254 | return itr->second; 255 | BOOST_THROW_EXCEPTION( bad_value_cast() ); 256 | } 257 | virtual iterator_impl_base* begin() { return new map_iterator_impl( this->get_val(), this->get_val().begin() ); } 258 | virtual const_iterator_impl_base* begin()const { return new const_map_iterator_impl( this->get_val(), this->get_val().begin() ); } 259 | }; 260 | template 261 | struct place_holder_const_map: public Base { 262 | place_holder_const_map( const std::map& v ):Base(v){} 263 | virtual bool is_array()const { return false; } 264 | virtual size_t size()const { return this->get_val().size(); } 265 | virtual bool has_field( const std::string& f )const { 266 | try { 267 | return this->get_val().find(boost::lexical_cast(f)) != this->get_val().end(); 268 | } catch ( ... ) { return false; } 269 | } 270 | virtual value_ref get_field( const std::string& f ) { 271 | BOOST_THROW_EXCEPTION( bad_value_cast() ); 272 | } 273 | virtual value_cref get_field( const std::string& f )const{ 274 | typename std::map::const_iterator itr = this->get_val().find(boost::lexical_cast(f)); 275 | if( itr != this->get_val().end() ) 276 | return itr->second; 277 | BOOST_THROW_EXCEPTION( bad_value_cast() ); 278 | } 279 | virtual iterator_impl_base* begin() { return 0; } 280 | virtual const_iterator_impl_base* begin()const { return new const_map_iterator_impl( this->get_val(), this->get_val().begin() ); } 281 | }; 282 | 283 | 284 | template 285 | struct select_place_holder { typedef place_holder_impl type; }; 286 | 287 | template 288 | struct select_place_holder,false > : public place_holder_array, place_holder_impl,false > > { 289 | select_place_holder( const std::vector& v ):place_holder_array, place_holder_impl,false > >(v){} 290 | select_place_holder( std::vector&& v ):place_holder_array, place_holder_impl,false > >(std::forward >(v)){} 291 | 292 | typedef select_place_holder type; 293 | }; 294 | template 295 | struct select_place_holder& > : public place_holder_array, place_holder_impl& > > { 296 | select_place_holder( std::vector& v ):place_holder_array, place_holder_impl& > >(v){}; 297 | typedef select_place_holder type; 298 | }; 299 | template 300 | struct select_place_holder& > : public place_holder_const_array, place_holder_impl& > > { 301 | select_place_holder( const std::vector& v ):place_holder_const_array, place_holder_impl& > >(v){}; 302 | typedef select_place_holder type; 303 | }; 304 | 305 | template 306 | struct select_place_holder,false > : public place_holder_array, place_holder_impl,false > > { 307 | select_place_holder( const std::map& v ):place_holder_map,false > >(v){} 308 | select_place_holder( std::map&& v ):place_holder_map,false > >(std::forward >(v)){} 309 | typedef select_place_holder type; 310 | }; 311 | template 312 | struct select_place_holder& > : public place_holder_map& > > { 313 | select_place_holder( std::map& v ):place_holder_map& > >(v){}; 314 | typedef select_place_holder type; 315 | }; 316 | template 317 | struct select_place_holder& > : public place_holder_const_map& > > { 318 | select_place_holder( const std::map& v ):place_holder_const_map& > >(v){}; 319 | typedef select_place_holder type; 320 | }; 321 | 322 | 323 | template 324 | class sequence_iterator_impl {}; 325 | 326 | template 327 | class sequence_iterator_impl : public iterator_impl_base { 328 | public: 329 | Seq& seq; 330 | int idx; 331 | 332 | sequence_iterator_impl( int i, Seq& s ):seq(s),idx(i){} 333 | 334 | virtual std::string key()const { return boost::lexical_cast(idx); } 335 | virtual value_ref value()const { return get_value_ref( seq, idx ); } 336 | virtual value_cref const_value()const { return get_value_ref(seq,idx); } 337 | virtual const_iterator_impl_base* const_clone()const { return new sequence_iterator_impl(idx,seq); } 338 | virtual iterator_impl_base* clone()const { return new sequence_iterator_impl(idx,seq); } 339 | 340 | virtual void next() { ++idx; } 341 | virtual bool equals( const const_iterator_impl_base* other )const{ 342 | if( other == 0 ) 343 | return idx == boost::fusion::result_of::size::value; 344 | 345 | if( type() == other->type() ) { 346 | return idx == static_cast*>(other)->idx; 347 | } 348 | } 349 | virtual const char* type()const { return get_typename(); } 350 | }; 351 | 352 | template 353 | class sequence_iterator_impl : public const_iterator_impl_base { 354 | public: 355 | const Seq& seq; 356 | int idx; 357 | 358 | sequence_iterator_impl( int i, const Seq& s ):seq(s),idx(i){} 359 | 360 | virtual std::string key()const { return boost::lexical_cast(idx); } 361 | virtual value_cref const_value()const { return get_value_ref(seq,idx); } 362 | virtual const_iterator_impl_base* const_clone()const { return new sequence_iterator_impl(idx,seq); } 363 | 364 | virtual void next() { ++idx; } 365 | virtual bool equals( const const_iterator_impl_base* other )const{ 366 | if( other == 0 ) 367 | return idx == boost::fusion::result_of::size::value; 368 | 369 | if( type() == other->type() ) { 370 | return idx == static_cast*>(other)->idx; 371 | } 372 | } 373 | virtual const char* type()const { return get_typename(); } 374 | }; 375 | 376 | template 377 | struct get_value_ref_visitor { 378 | mutable int idx; 379 | int target; 380 | mutable char ref[sizeof(value_ref)]; 381 | 382 | value_ref result()const { 383 | if( *((int64_t*)ref) == 0 ) 384 | BOOST_THROW_EXCEPTION( std::out_of_range( boost::lexical_cast(target) ) ); 385 | return *static_cast((void*)ref); 386 | } 387 | get_value_ref_visitor(int t=0):idx(0),target(t){} 388 | 389 | template 390 | inline void operator()( T& v )const { 391 | if( idx == target ) new(ref)value_ref(v); 392 | ++idx; 393 | } 394 | }; 395 | 396 | template 397 | struct get_value_ref_visitor { 398 | mutable int idx; 399 | int target; 400 | mutable char ref[sizeof(value_cref)]; 401 | value_cref& result()const { 402 | if( *((int64_t*)ref) == 0 ) 403 | BOOST_THROW_EXCEPTION( std::out_of_range( boost::lexical_cast(target) ) ); 404 | return *static_cast((void*)ref); 405 | } 406 | get_value_ref_visitor(int t=0):idx(0),target(t){memset(ref,0,sizeof(ref));} 407 | 408 | template 409 | inline void operator()( const T& v )const { 410 | if( idx == target ) new(ref)value_cref(v); 411 | ++idx; 412 | } 413 | }; 414 | 415 | template 416 | value_cref get_value_ref( const Seq& s, int idx ) { 417 | get_value_ref_visitor get_idx(idx); 418 | boost::fusion::for_each( s, get_idx ); 419 | return get_idx.result(); 420 | } 421 | template 422 | value_ref get_value_ref( Seq& s, int idx ) { 423 | get_value_ref_visitor get_idx(idx); 424 | boost::fusion::for_each( s, get_idx ); 425 | return get_idx.result(); 426 | } 427 | 428 | 429 | template 430 | struct place_holder_sequence : public Base { 431 | place_holder_sequence(){} 432 | place_holder_sequence( Seq v ):Base(v){} 433 | virtual bool is_array()const { return true; } 434 | virtual size_t size()const { return boost::fusion::result_of::size::type>::value; } 435 | virtual bool has_field( const std::string& f )const { 436 | try { 437 | uint64_t idx = boost::lexical_cast(f); 438 | return idx < size(); 439 | } catch ( ... ) { return false; } // bad lexical cast 440 | } 441 | virtual value_ref get_field( const std::string& f ) { 442 | uint64_t idx = boost::lexical_cast(f); 443 | return get_value_ref( this->get_val(), idx ); 444 | } 445 | virtual value_cref get_field( const std::string& f )const{ 446 | uint64_t idx = boost::lexical_cast(f); 447 | return get_value_ref( this->get_val(), idx ); 448 | } 449 | virtual value_ref get_field( uint64_t idx ) { return get_value_ref( this->get_val(), idx ); } 450 | virtual value_cref get_field( uint64_t idx )const { return get_value_ref( this->get_val(), idx ); } 451 | virtual iterator_impl_base* begin() { return new sequence_iterator_impl( 0,this->get_val()); } 452 | virtual const_iterator_impl_base* begin()const { return new sequence_iterator_impl( 0,this->get_val());} 453 | }; 454 | template 455 | struct place_holder_sequence : public Base { 456 | place_holder_sequence(){} 457 | place_holder_sequence( const Seq& v ):Base(v){} 458 | virtual bool is_array()const { return true; } 459 | virtual size_t size()const { return boost::fusion::result_of::size::type>::value; } 460 | virtual bool has_field( const std::string& f )const { 461 | try { 462 | uint64_t idx = boost::lexical_cast(f); 463 | return idx < size(); 464 | } catch ( ... ) { return false; } // bad lexical cast 465 | } 466 | virtual value_cref get_field( const std::string& f )const{ 467 | uint64_t idx = boost::lexical_cast(f); 468 | return get_value_ref( this->get_val(), idx ); 469 | } 470 | virtual value_cref get_field( uint64_t idx )const { return get_value_ref( this->get_val(), idx ); } 471 | virtual iterator_impl_base* begin() { return 0; } 472 | virtual const_iterator_impl_base* begin()const { return new sequence_iterator_impl( 0,this->get_val());} 473 | }; 474 | 475 | template 476 | struct select_sequence_holder: public place_holder_sequence > { 477 | select_sequence_holder( const Seq& v ):place_holder_sequence >(v){} 478 | select_sequence_holder( Seq&& v ):place_holder_sequence >(std::forward(v)){} 479 | typedef select_sequence_holder type; 480 | }; 481 | template 482 | struct select_sequence_holder : public place_holder_sequence > { 483 | select_sequence_holder( Seq& v ):place_holder_sequence >(v){}; 484 | typedef select_sequence_holder type; 485 | }; 486 | template 487 | struct select_sequence_holder : public place_holder_sequence > { 488 | select_sequence_holder( const Seq& v ):place_holder_sequence >(v){}; 489 | typedef select_sequence_holder type; 490 | }; 491 | 492 | 493 | template 494 | struct select_holder { 495 | typedef typename boost::mpl::if_c< 496 | boost::fusion::traits::is_sequence::type >::value, 497 | typename select_sequence_holder::type ) <= 3*sizeof(void*)>::type, 498 | typename select_place_holder ::type ) <= 3*sizeof(void*)>::type 499 | >::type type; 500 | }; 501 | 502 | 503 | } } } // boost::reflect::detail 504 | 505 | #endif 506 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/value.ipp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_DETAIL_VALUE_IPP_ 2 | #define _BOOST_REFLECT_DETAIL_VALUE_IPP_ 3 | #include 4 | #include 5 | 6 | namespace boost { namespace reflect { 7 | 8 | value::value( const value_cref& c) { 9 | *this = c.get_holder()->copy(); 10 | } 11 | value::value( const value_ref& c) { 12 | *this = c.get_holder()->copy(); 13 | } 14 | 15 | template 16 | value::value( const T& v ) { 17 | BOOST_STATIC_ASSERT( sizeof(held) >= sizeof(typename detail::select_holder::type) ); 18 | new(held) typename detail::select_holder::type(v); 19 | } 20 | 21 | template 22 | value::value( typename boost::remove_reference::type&& v ) { 23 | BOOST_STATIC_ASSERT( sizeof(held) >= sizeof(typename detail::select_holder::type) ); 24 | new(held) typename detail::select_holder::type(std::forward(v)); 25 | } 26 | 27 | value::value( value&& v ) { 28 | memcpy( held, v.held, sizeof(held) ); 29 | new(v.held) detail::place_holder(); 30 | } 31 | 32 | template 33 | value& value::operator=( const T& v ) { 34 | if( ptr() ) { *ptr() = v; return *this; } 35 | get_holder()->~place_holder(); 36 | 37 | new(held) typename detail::select_holder::type(v); 38 | return *this; 39 | } 40 | 41 | template 42 | value& value::operator=( T&& v ) { 43 | if( ptr() ) { *ptr() = std::forward(v); } 44 | else { 45 | new(held)typename detail::select_holder::type(std::forward(v)); 46 | } 47 | return *this; 48 | } 49 | 50 | template 51 | value& value::operator=( value&& v ) { 52 | memcpy(held,v.held,sizeof(held)); 53 | new (v.held) detail::place_holder(); 54 | return *this; 55 | } 56 | 57 | template 58 | value& value::operator=( const value& v ) { 59 | if( this != &v ) { 60 | get_holder()->~place_holder(); 61 | v.get_holder()->clone( held ); 62 | } 63 | return *this; 64 | } 65 | 66 | template 67 | value& value::operator=( const value_ref& v ){ 68 | return *this = v.get_holder()->copy(); 69 | } 70 | 71 | template 72 | value& value::operator=( const value_cref& v ) { 73 | return *this = v.get_holder()->copy(); 74 | } 75 | 76 | value_cref value::operator[]( const std::string& field )const { 77 | return get_holder()->get_field(field); 78 | } 79 | value_ref value::operator[]( const std::string& field ) { 80 | return get_holder()->get_field(field); 81 | } 82 | 83 | } } // boost::reflect 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/value_base.ipp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_DETAIL_VALUE_BASE_IPP_ 2 | #define _BOOST_REFLECT_DETAIL_VALUE_BASE_IPP_ 3 | #include 4 | #include 5 | #include 6 | namespace boost { namespace reflect { 7 | 8 | value_base::value_base() { new (held) detail::place_holder(); } 9 | value_base::~value_base() { get_holder()->~place_holder(); } 10 | value_base::value_base(const value_base& copy) 11 | { copy.get_holder()->clone( held ); } 12 | 13 | bool value_base::is_array()const { 14 | return get_holder()->is_array(); 15 | } 16 | size_t value_base::size()const { 17 | return get_holder()->size(); 18 | } 19 | 20 | /** 21 | * If a struct, iterates over fields 22 | * If a map, over keys 23 | * if an array, over indexes 24 | */ 25 | iterator value_base::begin() { 26 | return get_holder()->begin(); 27 | } 28 | const_iterator value_base::begin()const { 29 | return get_holder()->begin(); 30 | } 31 | iterator value_base::end() { 32 | return iterator(); 33 | } 34 | const_iterator value_base::end()const { 35 | return const_iterator(); 36 | } 37 | 38 | inline const detail::place_holder* value_base::get_holder()const { 39 | return reinterpret_cast(const_cast(held)); 40 | } 41 | inline detail::place_holder* value_base::get_holder(){ 42 | return reinterpret_cast(held); 43 | } 44 | 45 | const char* value_base::type()const { return get_holder()->type(); } 46 | 47 | void value_base::visit( read_value_visitor&& v )const { 48 | get_holder()->visit( std::forward(v) ); 49 | } 50 | void value_base::visit( write_value_visitor&& v ) { 51 | get_holder()->visit( std::forward(v) ); 52 | } 53 | 54 | template 55 | T value_base::as()const { 56 | T val; 57 | visit( get_visitor(val) ); 58 | return val; 59 | } 60 | 61 | template 62 | void value_base::set_as( const T&& v ) { 63 | visit( set_visitor( std::forward(v) ) ); 64 | } 65 | 66 | bool value_base::operator!()const { 67 | return get_holder()->type() == 0; 68 | } 69 | 70 | template 71 | inline const T* value_base::ptr()const { 72 | if( get_holder()->type() == get_typename() ) 73 | return static_cast( get_holder()->ptr() ); 74 | return 0; 75 | } 76 | template 77 | inline T* value_base::ptr(){ 78 | if( get_holder()->type() == get_typename() ) 79 | return static_cast( get_holder()->ptr() ); 80 | return 0; 81 | } 82 | 83 | 84 | bool value_base::has_field( const std::string& field )const{ 85 | return get_holder()->has_field(field); 86 | } 87 | 88 | template 89 | inline const T& value_base::get()const { 90 | const T* v = ptr(); 91 | if( v ) return *v; 92 | BOOST_THROW_EXCEPTION( bad_value_cast() ); 93 | } 94 | 95 | template 96 | inline T& value_base::get() { 97 | T* v = ptr(); 98 | if( v ) return *v; 99 | BOOST_THROW_EXCEPTION( bad_value_cast() ); 100 | } 101 | 102 | 103 | template 104 | value value_base::operator()(P1 p1)const { 105 | std::vector params(1); params[0] = p1; 106 | return get_holder()->call( params ); 107 | } 108 | template 109 | value value_base::operator()(P1 p1){ 110 | std::vector params(1); params[0] = p1; 111 | return get_holder()->call( params ); 112 | } 113 | 114 | template 115 | value value_base::operator()(P1 p1,P2 p2)const{ 116 | std::vector params(2); 117 | params[0] = p1; 118 | params[1] = p2; 119 | return get_holder()->call( params ); 120 | } 121 | 122 | template 123 | value value_base::operator()(P1 p1,P2 p2){ 124 | std::vector params(2); 125 | params[0] = p1; 126 | params[1] = p2; 127 | return get_holder()->call( params ); 128 | } 129 | 130 | 131 | 132 | } } // boost::reflect 133 | #endif // _BOOST_REFLECT_DETAIL_VALUE_BASE_IPP_ 134 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/value_cref.ipp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_DETAIL_VALUE_CREF_IPP_ 2 | #define _BOOST_REFLECT_DETAIL_VALUE_CREF_IPP_ 3 | #include 4 | #include 5 | #include 6 | 7 | namespace boost { namespace reflect { 8 | 9 | template 10 | value_cref::value_cref( const T&& t ) { 11 | BOOST_STATIC_ASSERT( sizeof(held) >= sizeof( typename detail::select_holder::type ) ); 12 | new (held) typename detail::select_holder::type( std::forward(t) ); 13 | } 14 | 15 | template 16 | value_cref::value_cref( const T& v ) { 17 | BOOST_STATIC_ASSERT( sizeof(held) >= sizeof( typename detail::select_holder::type ) ); 18 | new (held) typename detail::select_holder::type(v); 19 | } 20 | 21 | value_cref::value_cref( const value& v ) { 22 | v.get_holder()->cref().get_holder()->clone(held); 23 | } 24 | 25 | 26 | value_cref value_cref::operator[]( const std::string& field )const { 27 | return get_holder()->get_field( field ); 28 | } 29 | 30 | value_cref::value_cref( const value_cref& c ):value_base(c){} 31 | 32 | value_cref::value_cref( value_cref&& t ) { 33 | memcpy( held, t.held, sizeof(held) ); 34 | new (t.held) detail::place_holder(); 35 | } 36 | 37 | template 38 | inline const T& value_cref::get()const { 39 | const T* v = const_ptr(); 40 | if( v ) return *v; 41 | BOOST_THROW_EXCEPTION( bad_value_cast() ); 42 | } 43 | 44 | template 45 | inline const T* value_cref::const_ptr()const { 46 | if( get_holder()->type() == get_typename() ) 47 | return static_cast( get_holder()->ptr() ); 48 | return 0; 49 | } 50 | 51 | 52 | } } // namespace boost::reflect 53 | 54 | #endif // _BOOST_REFLECT_DETAIL_VALUE_CREF_IPP_ 55 | -------------------------------------------------------------------------------- /include/boost/reflect/detail/value_ref.ipp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_DETAIL_VALUE_REF_IPP_ 2 | #define _BOOST_REFLECT_DETAIL_VALUE_REF_IPP_ 3 | #include 4 | #include 5 | 6 | namespace boost { namespace reflect { 7 | value_ref::value_ref( const value_ref& r ):value_base(r){} 8 | 9 | value_ref::value_ref( value_ref&& v ) { 10 | memcpy( held, v.held, sizeof(held) ); 11 | new (v.held) detail::place_holder(); 12 | } 13 | 14 | value_ref::operator value_cref()const { 15 | return get_holder()->cref(); 16 | } 17 | 18 | template 19 | value_ref::value_ref( T& v ) { 20 | BOOST_STATIC_ASSERT( sizeof(typename detail::select_holder::type(v)) <= sizeof(held) ); 21 | new (held) typename detail::select_holder::type(v); 22 | } 23 | 24 | template 25 | value_ref& value_ref::operator=( const T& r ) { 26 | get() = r; 27 | return *this; 28 | } 29 | 30 | value_cref value_ref::operator[]( const std::string& field )const { 31 | return get_holder()->get_field(field); 32 | } 33 | value_ref value_ref::operator[]( const std::string& field ) { 34 | return get_holder()->get_field(field); 35 | } 36 | 37 | 38 | } } // namespace boost::reflect 39 | 40 | #endif // _BOOST_REFLECT_DETAIL_VALUE_REF_IPP_ 41 | -------------------------------------------------------------------------------- /include/boost/reflect/error.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_ERROR_HPP_ 2 | #define _BOOST_REFLECT_ERROR_HPP_ 3 | 4 | namespace boost { namespace reflect { 5 | 6 | typedef boost::error_info err_msg; 7 | 8 | class bad_value_cast : public std::bad_cast { 9 | public: 10 | virtual const char * what() const throw() { 11 | return "boost::reflect::bad_value_cast: " 12 | "failed conversion using boost::value"; 13 | } 14 | }; 15 | class unknown_field : public virtual boost::exception, public virtual std::exception { 16 | public: 17 | virtual const char * what() const throw() { 18 | return "boost::reflect::unknown_field: " 19 | "attempted to access an unknown field"; 20 | } 21 | }; 22 | } } // boost::reflect 23 | #endif 24 | -------------------------------------------------------------------------------- /include/boost/reflect/iterator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_ITERATOR_HPP_ 2 | #define _BOOST_REFLECT_ITERATOR_HPP_ 3 | #include 4 | 5 | namespace boost { namespace reflect { 6 | 7 | namespace detail { 8 | class const_iterator_impl_base; 9 | class iterator_impl_base; 10 | } 11 | class value_ref; 12 | class value_cref; 13 | 14 | class iterator { 15 | public: 16 | std::string key()const; 17 | value_ref value()const; 18 | 19 | // 0 == end 20 | iterator( const iterator& i ); 21 | iterator( iterator&& i ); 22 | iterator( detail::iterator_impl_base* p = 0 ); 23 | ~iterator(); 24 | 25 | iterator& operator=( const iterator& i ); 26 | 27 | iterator& operator++(int); 28 | iterator& operator++(); 29 | 30 | bool operator == ( const iterator& i )const; 31 | bool operator != ( const iterator& i )const; 32 | 33 | private: 34 | friend class const_iterator; 35 | detail::iterator_impl_base* itr; 36 | }; 37 | 38 | class const_iterator { 39 | public: 40 | std::string key()const; 41 | value_cref value()const; 42 | 43 | const_iterator( detail::const_iterator_impl_base* b = 0 ); 44 | const_iterator( const iterator& i ); 45 | const_iterator( const const_iterator& i ); 46 | const_iterator( const_iterator&& i ); 47 | ~const_iterator(); 48 | 49 | const_iterator& operator++(int); 50 | const_iterator& operator++(); 51 | 52 | bool operator == ( const const_iterator& i )const; 53 | bool operator != ( const const_iterator& i )const; 54 | 55 | private: 56 | friend class iterator; 57 | detail::const_iterator_impl_base* itr; 58 | }; 59 | 60 | } }//boost::reflect 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/boost/reflect/mirror_interface.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BOOST_PP_IS_ITERATING 2 | #ifndef BOOST_REFLECT_MIRROR_INTERFACE_HPP 3 | #define BOOST_REFLECT_MIRROR_INTERFACE_HPP 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace boost { namespace reflect { 17 | /** 18 | * @brief Specialized to mirror the member 19 | * variable/method pointed to by MemberPtr 20 | */ 21 | template 22 | struct mirror_member; 23 | 24 | namespace detail { 25 | namespace mirror_interface { 26 | #ifndef DOXYGEN 27 | /** 28 | * Assigns VTableType's functors with values from T 29 | */ 30 | template 31 | class set_visitor { 32 | public: 33 | set_visitor( VTableType& vt, T& self ) 34 | :m_self(self),vtbl(vt){} 35 | 36 | template 37 | void operator()( const char* name )const { 38 | typedef typename boost::function_types::result_type::type member_ref; 39 | typedef typename boost::remove_reference::type member; 40 | assign a(m_self,vtbl.*m); 41 | member::template get_member_ptr( a ); 42 | } 43 | private: 44 | template 45 | struct assign { 46 | assign( T& _v, Member& _m ):v(_v),m(_m){} 47 | 48 | template 49 | void operator=( const MemberPtr& p ) { 50 | m.set_delegate( &v, p ); 51 | } 52 | private: 53 | T& v; 54 | Member& m; 55 | }; 56 | T& m_self; 57 | VTableType& vtbl; 58 | }; 59 | template 60 | class set_visitor, VTableType> { 61 | public: 62 | typedef boost::reflect::vtable T; 63 | 64 | set_visitor( VTableType& vt, T& self ) 65 | :m_self(self),vtbl(vt){} 66 | 67 | template // M (InterfaceName::*m 68 | void operator()( const char* name )const { 69 | typedef typename boost::function_types::result_type::type member_ref; 70 | typedef typename boost::remove_reference::type member; 71 | assign a(m_self,vtbl.*m); 72 | member::template get_member_ptr( a ); 73 | } 74 | private: 75 | template 76 | struct assign { 77 | assign( T& _v, Member& _m ):v(_v),m(_m){} 78 | 79 | template 80 | void operator=( MemberPtr p ) { 81 | m = boost::bind(boost::ref(v.*p), _1 ); 82 | } 83 | private: 84 | T& v; 85 | Member& m; 86 | }; 87 | T& m_self; 88 | VTableType& vtbl; 89 | }; 90 | 91 | #endif 92 | } 93 | } 94 | 95 | /** 96 | * @brief Interface Delegate that mirrors the 97 | * reflected interface without any transformation. 98 | * 99 | * To specialize how a particular member is mirrored define 100 | * the partial specialization of mirror_member for your type. 101 | * 102 | * @code 103 | * template 104 | * mirror_member 105 | * @endcode 106 | */ 107 | struct mirror_interface 108 | { 109 | /** 110 | * @brief Implements the InterfaceDelegate meta-function to 111 | * determine what type to create to mirror MemberPointer 112 | * in boost::reflect::vtable used by boost::reflect::any_ptr 113 | */ 114 | template 115 | struct calculate_type { 116 | typedef mirror_member type; 117 | }; 118 | 119 | template 120 | static void set_vtable( VTableType& vtable, T& value ) { 121 | vtable_reflector::visit( &vtable, 122 | detail::mirror_interface::set_visitor(vtable,value) ); 123 | } 124 | template 125 | static void set_vtable( VTableType& vtable, const T& value ) { 126 | vtable_reflector::visit( &vtable, 127 | detail::mirror_interface::set_visitor(vtable,value) ); 128 | } 129 | }; 130 | 131 | #ifndef DOXYGEN 132 | 133 | /** 134 | * Blocks a signal if it is currently unblocked and 135 | * unblocks it when it goes out of scope if it was blocked 136 | * when constructed. 137 | */ 138 | struct scoped_block_signal { 139 | scoped_block_signal( boost::signals::connection& _c ) 140 | :c(_c),unblock(false){ 141 | if( c != boost::signals::connection() && !c.blocked() ) { 142 | unblock = true; 143 | c.block(); 144 | } 145 | } 146 | ~scoped_block_signal() { 147 | if( unblock && c != boost::signals::connection() ) 148 | c.unblock(); 149 | } 150 | private: 151 | bool unblock; 152 | boost::signals::connection& c; 153 | }; 154 | #endif 155 | 156 | 157 | #define PARAM_NAME(z,n,type) BOOST_PP_CAT(a,n) 158 | #define PARAM_PLACE_HOLDER(z,n,type) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1) ) 159 | #define PARAM_TYPE_NAME(z,n,type) BOOST_PP_CAT(typename A,n) 160 | #define PARAM_TYPE(z,n,type) BOOST_PP_CAT(A,n) 161 | #define PARAM_ARG(z,n,type) PARAM_TYPE(z,n,type) PARAM_NAME(z,n,type) 162 | #define DEDUCE_PARAM_TYPE(z,in,Type) typename boost::remove_const::type >::type 163 | 164 | # ifndef BOOST_REFLECT_MIRROR_IMPL_SIZE 165 | # define BOOST_REFLECT_MIRROR_IMPL_SIZE 8 166 | # endif 167 | 168 | # include 169 | # define BOOST_PP_ITERATION_LIMITS (0, BOOST_REFLECT_MIRROR_IMPL_SIZE -1 ) 170 | # define BOOST_PP_FILENAME_1 171 | # include BOOST_PP_ITERATE() 172 | 173 | #undef PARAM_NAME 174 | #undef PARAM_TYPE 175 | #undef PARAM_ARG 176 | #undef DEDUCE_PARAM_TYPE 177 | 178 | } } // namespace boost::reflect 179 | #endif // BOOST_REFLECT_MIRROR_INTERFACE_HPP 180 | 181 | #else // BOOST_PP_IS_ITERATING 182 | 183 | #define n BOOST_PP_ITERATION() 184 | #define PARAM_NAMES BOOST_PP_ENUM(n,PARAM_NAME,A) // name_N 185 | #define PARAM_PLACE_HOLDERS BOOST_PP_ENUM_TRAILING(n,PARAM_PLACE_HOLDER,A) // _(N+1) 186 | #define PARAM_ARGS BOOST_PP_ENUM(n,PARAM_ARG,A) // TYPE_N name_N 187 | #define PARAM_TYPE_NAMES BOOST_PP_ENUM(n,PARAM_TYPE_NAME,A) // typename TYPE_N 188 | #define PARAM_TYPES BOOST_PP_ENUM(n,PARAM_TYPE,A) // TYPE_N 189 | #define DEDUCED_PARAM_TYPES BOOST_PP_ENUM(n,DEDUCE_PARAM_TYPE,A) // TYPE_N 190 | 191 | template 192 | struct mirror_member 193 | { 194 | // boost::result_of 195 | typedef typename adapt_void::result_type result_type; 196 | typedef mirror_member self_type; 197 | typedef boost::fusion::vector fused_params; 198 | typedef boost::fusion::vector deduced_params; 199 | typedef boost::function_traits traits; 200 | static const bool is_const = true; 201 | static const bool is_signal = false; 202 | 203 | typedef typename boost::remove_pointer::type signature; 204 | 205 | result_type operator()( PARAM_ARGS )const { 206 | return m_delegate( boost::fusion::make_vector(PARAM_NAMES) ); 207 | } 208 | result_type operator() ( const fused_params& fp )const { 209 | return m_delegate( fp ); 210 | } 211 | mirror_member& operator=( const mirror_member& d ) { 212 | m_delegate = d.m_delegate; 213 | return *this; 214 | } 215 | template 216 | mirror_member& operator=( const T& d ) { 217 | m_delegate = adapt_void(d); 218 | return *this; 219 | } 220 | template 221 | void set_delegate( C* s, M m ) { 222 | m_delegate = adapt_void >( 223 | boost::fusion::make_fused_function_object( 224 | boost::bind(m,s PARAM_PLACE_HOLDERS ) )); 225 | } 226 | private: 227 | boost::function m_delegate; 228 | }; 229 | 230 | template 231 | struct mirror_member 232 | { 233 | typedef typename adapt_void::result_type result_type; 234 | 235 | typedef mirror_member self_type; 236 | typedef boost::fusion::vector fused_params; 237 | typedef boost::fusion::vector deduced_params; 238 | typedef boost::function_traits traits; 239 | typedef boost::function delegate_type; 240 | static const bool is_const = false; 241 | static const bool is_signal = false; 242 | 243 | // boost::result_of 244 | typedef typename boost::remove_pointer::type signature; 245 | 246 | result_type operator()( PARAM_ARGS ) { 247 | return m_delegate( boost::fusion::make_vector(PARAM_NAMES) ); 248 | } 249 | result_type operator() ( const fused_params& fp ) { 250 | return m_delegate( fp ); 251 | } 252 | template 253 | mirror_member& operator=( const T& d ) { 254 | m_delegate = adapt_void(d); 255 | return *this; 256 | } 257 | template 258 | void set_delegate( C* s, M m ) { 259 | m_delegate = adapt_void >( 260 | boost::fusion::make_fused_function_object( 261 | boost::bind(m,s PARAM_PLACE_HOLDERS ) )); 262 | } 263 | private: 264 | delegate_type m_delegate; 265 | }; 266 | 267 | 268 | template 269 | struct mirror_member< boost::signal (Class::*) > 270 | { 271 | typedef typename adapt_void::result_type result_type; 272 | typedef mirror_member self_type; 273 | typedef boost::fusion::vector fused_params; 274 | typedef boost::function_traits traits; 275 | typedef boost::signal signal_type; 276 | static const bool is_const = false; 277 | static const bool is_signal = true; 278 | 279 | // boost::result_of 280 | typedef typename boost::remove_pointer::type signature; 281 | 282 | result_type operator()( PARAM_ARGS ) { 283 | return (*this)( boost::fusion::make_vector(PARAM_NAMES) ); 284 | } 285 | 286 | result_type operator() ( const fused_params& fp ) { 287 | scoped_block_signal block_reverse(m_reverse_con); 288 | if( int(m_signal.num_slots()) - 1 > 0 ) // do not count our reverse connection 289 | boost::fusion::make_fused_function_object( boost::ref(m_signal) )(fp); 290 | return m_delegate( fp ); 291 | } 292 | 293 | // emits locally, but does not forward to delegate 294 | result_type emit( const fused_params& fp ) { 295 | scoped_block_signal block_reverse(m_reverse_con); 296 | return adapt_void >( 297 | boost::fusion::make_fused_function_object( boost::ref(m_signal) ) )(fp); 298 | } 299 | 300 | template 301 | mirror_member& operator=( const T& d ) { 302 | m_delegate = adapt_void(d); 303 | return *this; 304 | } 305 | 306 | template 307 | boost::signals::connection connect( const Functor& f ) { 308 | boost::signals::connection c = m_signal.connect(adapt_void(f) ); 309 | if( m_connect_delegate ) 310 | m_connect_delegate(m_signal.num_slots()); 311 | return c; 312 | } 313 | void disconnect( const boost::signals::connection& c ) { 314 | c.disconnect(); 315 | if( m_connect_delegate ) 316 | m_connect_delegate(m_signal.num_slots()); 317 | } 318 | 319 | void set_connect_delegate( const boost::function& f ) { 320 | m_connect_delegate = f; 321 | } 322 | 323 | // sets the delegate that will be called when the signal is 'emited' 324 | template 325 | void set_delegate( C* s, M m ) { 326 | m_signal.disconnect_all_slots(); 327 | m_reverse_con = 328 | (s->*m).connect( boost::fusion::make_unfused( 329 | boost::bind( &mirror_member::emit, this, _1) ) ); 330 | 331 | m_delegate = emit_or_throw( s->*m ); 332 | } 333 | 334 | ~mirror_member() { 335 | m_signal.disconnect_all_slots(); 336 | if( m_reverse_con != boost::signals::connection() ) 337 | m_reverse_con.disconnect(); 338 | } 339 | 340 | private: 341 | 342 | struct emit_or_throw { 343 | struct no_connected_slots : public std::exception, public boost::exception { 344 | const char* what()const throw() { return "no connected slots"; } 345 | }; 346 | emit_or_throw( signal_type& s ):sig(s){} 347 | result_type operator()( const fused_params& p ) { 348 | if( int(sig.num_slots()) -1 > 0 ) { // do not count our reverse connection 349 | return adapt_void >( 350 | boost::fusion::make_fused_function_object(boost::ref(sig)))(p); 351 | } 352 | BOOST_THROW_EXCEPTION( no_connected_slots() ); 353 | } 354 | signal_type& sig; 355 | }; 356 | 357 | boost::function m_connect_delegate; 358 | boost::function m_delegate; 359 | boost::signals::connection m_reverse_con; 360 | boost::signal m_signal; 361 | }; 362 | 363 | #undef n 364 | #undef PARAM_NAMES 365 | #undef PARAM_PLACE_HOLDERS 366 | #undef PARAM_ARGS 367 | #undef PARAM_TYPE_NAMES 368 | #undef PARAM_TYPES 369 | 370 | #endif // BOOST_PP_IS_ITERATING 371 | -------------------------------------------------------------------------------- /include/boost/reflect/old.hpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef DOXYGEN 4 | #define CUSTOM_MEMBER_CASES(r, data, i, elem)\ 5 | case BOOST_PP_TUPLE_ELEM( 3, 1, elem ):\ 6 | v.accept_member( name, &data::BOOST_PP_TUPLE_ELEM(3, 0, elem), BOOST_PP_STRINGIZE( BOOST_PP_TUPLE_ELEM(3,0,elem) ), BOOST_PP_TUPLE_ELEM(3, 2,elem) );\ 7 | break; 8 | 9 | #define CUSTOM_MEMBER_ALL(r, data, i, elem)\ 10 | v.accept_member( name, &data::BOOST_PP_TUPLE_ELEM(3, 0, elem), BOOST_PP_STRINGIZE( BOOST_PP_TUPLE_ELEM(3,0,elem) ), BOOST_PP_TUPLE_ELEM(3, 2,elem) );\ 11 | 12 | #define MEMBER_CASES(r, data, i, elem)\ 13 | case i:\ 14 | v.accept_member( name, &data::elem, BOOST_PP_STRINGIZE( elem ), i ); \ 15 | break; 16 | 17 | #define MEMBER_ALL(r, data, i, elem)\ 18 | v.accept_member( name, &data::elem, BOOST_PP_STRINGIZE( elem ), i ); 19 | 20 | #define INHERITS (baseA)(baseB) 21 | 22 | #define ACCEPT_BASE(r, data, i, elem) \ 23 | v.accept_base( *static_cast(&name), BOOST_PP_STRINGIZE( elem ), field ); 24 | 25 | 26 | #define BOOST_REFLECT_IMPL( CONST,TYPE, INHERITS, MEMBERS ) \ 27 | template\ 28 | static inline void visit( CONST TYPE& name, Visitor& v, uint32_t field = -1 ) { \ 29 | v.start(name, BOOST_PP_STRINGIZE(TYPE) );\ 30 | BOOST_PP_SEQ_FOR_EACH_I( ACCEPT_BASE, TYPE, INHERITS ) \ 31 | switch( field ) { \ 32 | case -1: \ 33 | BOOST_PP_SEQ_FOR_EACH_I( MEMBER_ALL, TYPE, MEMBERS ) \ 34 | break; \ 35 | BOOST_PP_SEQ_FOR_EACH_I( MEMBER_CASES, TYPE, MEMBERS ) \ 36 | default: \ 37 | v.not_found( name, field );\ 38 | }\ 39 | v.end(name, BOOST_PP_STRINGIZE(TYPE) );\ 40 | } \ 41 | 42 | #define BOOST_REFLECT_CUSTOM_IMPL( CONST,TYPE, INHERITS, MEMBERS ) \ 43 | template\ 44 | static inline void visit( CONST TYPE& name, Visitor& v, uint32_t field = -1 ) { \ 45 | v.start(name, BOOST_PP_STRINGIZE(TYPE) );\ 46 | BOOST_PP_SEQ_FOR_EACH_I( ACCEPT_BASE, TYPE, INHERITS ) \ 47 | switch( field ) { \ 48 | case -1: \ 49 | BOOST_PP_SEQ_FOR_EACH_I( CUSTOM_MEMBER_ALL, TYPE, MEMBERS ) \ 50 | break; \ 51 | BOOST_PP_SEQ_FOR_EACH_I( CUSTOM_MEMBER_CASES, TYPE, MEMBERS ) \ 52 | default: \ 53 | v.not_found( name, field );\ 54 | }\ 55 | v.end(name, BOOST_PP_STRINGIZE(TYPE) );\ 56 | } \ 57 | 58 | #define BOOST_REFLECT_EMPTY 59 | 60 | #define VISIT_BASE( r, data, elem ) reflector::visit( *((vtable*)&a), data ); 61 | #define VISIT_MEMBER( r, data, elem ) t.template accept( a.elem, BOOST_PP_STRINGIZE(elem) ); 62 | #endif // DOXYGEN 63 | 64 | /** 65 | * @brief Specializes boost::reflect::reflector for TYPE 66 | * 67 | * @param INHERITS - a sequence of base class names (basea)(baseb)(basec) 68 | * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) 69 | */ 70 | #define BOOST_REFLECT( TYPE, INHERITS, MEMBERS ) \ 71 | BOOST_REFLECT_TYPEINFO(TYPE) \ 72 | namespace boost { namespace reflect { \ 73 | template<> struct reflector {\ 74 | BOOST_REFLECT_IMPL( const, TYPE, INHERITS, MEMBERS ) \ 75 | BOOST_REFLECT_IMPL( BOOST_REFLECT_EMPTY, TYPE, INHERITS, MEMBERS ) \ 76 | \ 77 | template \ 78 | static void visit( boost::reflect::vtable& a, T& t ) { \ 79 | BOOST_PP_SEQ_FOR_EACH( VISIT_BASE, t, INHERITS ) \ 80 | BOOST_PP_SEQ_FOR_EACH( VISIT_MEMBER, TYPE, MEMBERS ) \ 81 | } \ 82 | }; } } 83 | 84 | 85 | /** 86 | * This macro is identical to BOOST_REFLECT, except that it gives you 87 | * the ability to customize field numbers and flags. 88 | * 89 | * @param MEMBERS - a sequence of 3 param tuples. 90 | * ((field_name, NUMBER, FLAGS))((field_name1, NUMBER, FLAGS)) 91 | * 92 | */ 93 | #define BOOST_REFLECT_CUSTOM( TYPE, INHERITS, MEMBERS ) \ 94 | BOOST_REFLECT_TYPEINFO(TYPE) \ 95 | namespace boost { namespace reflect { \ 96 | template<> struct reflector { \ 97 | BOOST_REFLECT_CUSTOM_IMPL( const, TYPE, INHERITS, MEMBERS ) \ 98 | BOOST_REFLECT_CUSTOM_IMPL( BOOST_REFLECT_EMPTY, TYPE, INHERITS, MEMBERS ) \ 99 | } } } 100 | -------------------------------------------------------------------------------- /include/boost/reflect/reflect.hpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file boost/reflect/reflect.hpp 4 | * 5 | * @brief Defines types and macros used to provide reflection. 6 | * 7 | */ 8 | #ifndef _BOOST_REFLECT_HPP_ 9 | #define _BOOST_REFLECT_HPP_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace boost { namespace reflect { 34 | 35 | /** 36 | * @brief defines visit functions for T 37 | * Unless this is specialized, visit() will not be defined for T. 38 | * 39 | * The @ref BOOST_REFLECT(TYPE,INHERITS,MEMBERS) macro is used to specialize this 40 | * class for your type. 41 | */ 42 | template 43 | struct reflector{ 44 | typedef T type; 45 | typedef boost::fusion::vector<> base_class_types; 46 | typedef boost::false_type is_defined; 47 | template 48 | static inline void visit( const Visitor& ){}; 49 | }; 50 | 51 | } } // namespace boost::reflect 52 | 53 | #ifndef DOXYGEN 54 | 55 | #define BOOST_REFLECT_VISIT_BASE(r, visitor, base) \ 56 | boost::reflect::reflector::visit( visitor ); 57 | 58 | #define BOOST_REFLECT_VISIT_MEMBER( r, visitor, elem ) \ 59 | visitor.template operator()( BOOST_PP_STRINGIZE(elem) ); 60 | 61 | #define BOOST_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ 62 | template\ 63 | static inline void visit( const Visitor& v ) { \ 64 | BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VISIT_BASE, v, INHERITS ) \ 65 | BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VISIT_MEMBER, v, MEMBERS ) \ 66 | } 67 | 68 | #define BOOST_REFLECT_DERIVED_IMPL_EXT( TYPE, INHERITS, MEMBERS ) \ 69 | template\ 70 | void boost::reflect::reflector::visit( const Visitor& v ) { \ 71 | BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VISIT_BASE, v, INHERITS ) \ 72 | BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VISIT_MEMBER, v, MEMBERS ) \ 73 | } 74 | 75 | #endif // DOXYGEN 76 | 77 | /** 78 | * @brief Specializes boost::reflect::reflector for TYPE where 79 | * type inherits other reflected classes 80 | * 81 | * @param INHERITS - a sequence of base class names (basea)(baseb)(basec) 82 | * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) 83 | */ 84 | #define BOOST_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \ 85 | BOOST_REFLECT_TYPEINFO(TYPE) \ 86 | namespace boost { namespace reflect { \ 87 | template<> struct reflector {\ 88 | typedef TYPE type; \ 89 | typedef boost::true_type is_defined; \ 90 | BOOST_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \ 91 | }; } } 92 | 93 | 94 | /** 95 | * @brief Specializes boost::reflect::reflector for TYPE 96 | * 97 | * @param MEMBERS - a sequence of member names. (field1)(field2)(field3) 98 | * 99 | * @see BOOST_REFLECT_DERIVED 100 | */ 101 | #define BOOST_REFLECT( TYPE, MEMBERS ) \ 102 | BOOST_REFLECT_DERIVED( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) 103 | 104 | #define BOOST_REFLECT_FWD( TYPE ) \ 105 | BOOST_REFLECT_TYPEINFO(TYPE) \ 106 | namespace boost { namespace reflect { \ 107 | template<> struct reflector {\ 108 | typedef TYPE type; \ 109 | typedef boost::true_type is_defined; \ 110 | template static void visit( const Visitor& v ); \ 111 | }; } } 112 | 113 | 114 | #define BOOST_REFLECT_DERIVED_IMPL( TYPE, MEMBERS ) \ 115 | BOOST_REFLECT_IMPL_DERIVED_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) 116 | 117 | #define BOOST_REFLECT_IMPL( TYPE, MEMBERS ) \ 118 | BOOST_REFLECT_DERIVED_IMPL_EXT( TYPE, BOOST_PP_SEQ_NIL, MEMBERS ) 119 | 120 | 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /include/boost/reflect/reflect_function_signature.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BOOST_PP_IS_ITERATING 2 | 3 | # ifndef BOOST_REFLECT_FUNCTION_SIGNATURE_HPP 4 | # define BOOST_REFLECT_FUNCTION_SIGNATURE_HPP 5 | 6 | # include 7 | # include 8 | # include 9 | # include 10 | # include 11 | # include 12 | # include 13 | # include 14 | 15 | # ifndef GET_REFLECT_PARAMETER_SIZE 16 | # define GET_REFLECT_PARAMETER_SIZE 8 17 | # endif 18 | 19 | 20 | namespace boost { namespace reflect { 21 | 22 | #ifndef RCR 23 | #define RCR(X) typename boost::remove_const::type>::type 24 | #endif 25 | 26 | #define ADD_PARAM(z,n,v) *sig += get_typename() \ 27 | BOOST_PP_EXPR_IF( BOOST_PP_LESS(n,v), + std::string(",") ); 28 | 29 | # include 30 | # define BOOST_PP_ITERATION_LIMITS (0, GET_REFLECT_PARAMETER_SIZE ) 31 | # define BOOST_PP_FILENAME_1 32 | # include BOOST_PP_ITERATE() 33 | 34 | #undef PARAM_TYPE 35 | #undef PARAM_NAME 36 | #undef PARAM_ARG 37 | #undef ADD_PARAM 38 | #undef RCR 39 | } } // boost::reflect 40 | 41 | # endif // BOOST_REFLECT_FUNCTION_SIGNATURE_HPP 42 | 43 | #else // BOOST_PP_IS_ITERATING 44 | 45 | # define n BOOST_PP_ITERATION() 46 | 47 | template 48 | struct get_typeinfo 49 | { 50 | static const char* name() 51 | { 52 | static std::string* sig = NULL; 53 | if( !sig ) 54 | { 55 | sig = new std::string( get_typename() ); 56 | *sig += '('; 57 | BOOST_PP_REPEAT( n, ADD_PARAM, BOOST_PP_SUB(n,1) ) 58 | *sig += ')'; 59 | } 60 | return sig->c_str(); 61 | } 62 | }; 63 | 64 | 65 | 66 | #undef n 67 | 68 | 69 | #endif // BOOST_PP_IS_ITERATING 70 | -------------------------------------------------------------------------------- /include/boost/reflect/typeinfo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_TYPEINFO_HPP 2 | #define _BOOST_REFLECT_TYPEINFO_HPP 3 | namespace boost { namespace reflect { 4 | 5 | /** 6 | * @brief provides compile time access to name of a type. 7 | */ 8 | template 9 | struct get_typeinfo { 10 | enum is_defined_enum{ is_defined = 0 }; 11 | static const char* name() { return typeid(T).name(); } 12 | }; 13 | 14 | /** 15 | * @brief Removes all decorations and returns the typename. 16 | */ 17 | template 18 | inline const char* get_typename() { 19 | return get_typeinfo::type>::type>::type>::name(); 22 | } 23 | #ifndef DOXYGEN 24 | template 25 | struct get_typeinfo< std::vector > { 26 | enum is_defined_enum{ is_defined = get_typeinfo::is_defined }; 27 | static const char* name() 28 | { 29 | static std::string n = "std::vector<" + std::string(get_typename()) + ">"; 30 | return n.c_str(); 31 | } 32 | }; 33 | template 34 | struct get_typeinfo< std::list > { 35 | enum is_defined_enum{ is_defined = get_typeinfo::is_defined }; 36 | static const char* name() 37 | { 38 | static std::string n = "std::list<" + std::string(get_typename()) + ">"; 39 | return n.c_str(); 40 | } 41 | }; 42 | 43 | template 44 | struct get_typeinfo< std::map > { 45 | enum is_defined_enum{ is_defined = get_typeinfo::is_defined && get_typeinfo::is_defined }; 46 | static const char* name() 47 | { 48 | // TODO: make thread safe... 49 | static std::string n = "std::map<" + std::string(get_typename()) + "," + 50 | std::string(get_typename() ) + ">"; 51 | return n.c_str(); 52 | } 53 | }; 54 | #endif 55 | 56 | /** 57 | * @brief Allows the typename to be accessed via get_typename() in a 58 | * cross-platform, demangled way that std::typeinfo cannot do. 59 | */ 60 | #define BOOST_REFLECT_TYPEINFO( NAME ) \ 61 | namespace boost { namespace reflect { \ 62 | template<> struct get_typeinfo { \ 63 | enum is_defined_enum{ is_defined = 1 }; \ 64 | static const char* name() { return BOOST_PP_STRINGIZE(NAME); } \ 65 | }; } } 66 | 67 | #define BOOST_REFLECT_TYPEINFO_ALIAS( NAME, STR_NAME ) \ 68 | namespace boost { namespace reflect { \ 69 | template<> struct get_typeinfo { \ 70 | enum is_defined_enum{ is_defined = 1 }; \ 71 | static const char* name() { return STR_NAME; } \ 72 | }; } } 73 | 74 | 75 | /** 76 | * @brief Same as BOOST_REFLECT_TYPEINFO except works for templates with 1 paramater. 77 | */ 78 | #define BOOST_REFLECT_TEMPLATE_TYPEINFO( NAME ) \ 79 | namespace boost { namespace reflect {\ 80 | template<> struct get_typeinfo > { \ 81 | enum is_defined_enum{ is_defined = 1 }; \ 82 | static const char* name() { return BOOST_PP_STRINGIZE(NAME); } \ 83 | }; } } 84 | 85 | /** 86 | * @brief Same as BOOST_REFLECT_TYPEINFO except works for templates with 2 paramaters. 87 | */ 88 | #define BOOST_REFLECT_TEMPLATE2_TYPEINFO( NAME ) \ 89 | namespace boost { namespace reflect {\ 90 | template<> struct get_typeinfo > { \ 91 | enum is_defined_enum{ is_defined = 1 }; \ 92 | static const char* name() { return BOOST_PP_STRINGIZE(NAME); } \ 93 | }; } } 94 | 95 | } } // boost::reflect 96 | 97 | 98 | // these macros specify namespace boost::reflect 99 | BOOST_REFLECT_TYPEINFO( void ) 100 | BOOST_REFLECT_TYPEINFO( bool ) 101 | BOOST_REFLECT_TYPEINFO( uint8_t ) 102 | BOOST_REFLECT_TYPEINFO( uint16_t ) 103 | BOOST_REFLECT_TYPEINFO( uint32_t ) 104 | BOOST_REFLECT_TYPEINFO( uint64_t ) 105 | BOOST_REFLECT_TYPEINFO( int8_t ) 106 | BOOST_REFLECT_TYPEINFO( int16_t ) 107 | BOOST_REFLECT_TYPEINFO( int32_t ) 108 | BOOST_REFLECT_TYPEINFO( int64_t ) 109 | BOOST_REFLECT_TYPEINFO( double ) 110 | BOOST_REFLECT_TYPEINFO( float ) 111 | BOOST_REFLECT_TYPEINFO( void_t ) 112 | BOOST_REFLECT_TYPEINFO( std::string ) 113 | BOOST_REFLECT_TEMPLATE_TYPEINFO( std::vector ) 114 | BOOST_REFLECT_TEMPLATE_TYPEINFO( std::set ) 115 | BOOST_REFLECT_TEMPLATE_TYPEINFO( std::list ) 116 | BOOST_REFLECT_TEMPLATE2_TYPEINFO( std::map ) 117 | BOOST_REFLECT_TEMPLATE2_TYPEINFO( std::pair ) 118 | 119 | #include 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /include/boost/reflect/value.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_VALUE_HPP_ 2 | #define _BOOST_REFLECT_VALUE_HPP_ 3 | #include 4 | 5 | namespace boost { namespace reflect { 6 | 7 | /** 8 | * A value may hold any type and provides polymorphic 9 | * access to its members by name. In general a value 10 | * may hold a struct, array, map, number, string, null, 11 | * bool, or function. 12 | * 13 | * @code 14 | * struct test { 15 | * int num; 16 | * std::string str; 17 | * int print( std::string& ); 18 | * }; 19 | * value v(test()); 20 | * v["num"].as(); 21 | * v["num"].as(); 22 | * v["str"].as(); 23 | * v["str"].as(); 24 | * v["print"]( "hello world" ); 25 | * 26 | * @endcode 27 | * 28 | * Given a value you can iterate over its members and 29 | * perform actions. 30 | * 31 | */ 32 | class value : public value_base { 33 | public: 34 | value(){} 35 | 36 | template 37 | value( const T& v ); 38 | 39 | value( value&& v ); 40 | 41 | template 42 | value( typename boost::remove_reference::type&& v ); 43 | 44 | value( const value_cref& ); 45 | value( const value_ref& ); 46 | 47 | template 48 | value& operator=( const T& v ); 49 | 50 | template 51 | value& operator=( T&& v ); 52 | 53 | template 54 | value& operator=( value&& v ); 55 | 56 | template 57 | value& operator=( const value& v ); 58 | 59 | template 60 | value& operator=( const value_ref& v ); 61 | 62 | template 63 | value& operator=( const value_cref& v ); 64 | 65 | value_cref operator[]( const std::string& field )const; 66 | value_ref operator[]( const std::string& field ); 67 | value_cref operator[]( uint64_t idx )const; 68 | value_ref operator[]( uint64_t idx ); 69 | }; 70 | 71 | 72 | } } // namespace boost 73 | 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/boost/reflect/value_base.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_VALUE_BASE_HPP_ 2 | #define _BOOST_REFLECT_VALUE_BASE_HPP_ 3 | #include 4 | #include 5 | 6 | namespace boost { namespace reflect { 7 | namespace detail { 8 | class place_holder; 9 | }; 10 | 11 | class iterator; 12 | class value; 13 | class const_iterator; 14 | 15 | class value_base { 16 | public: 17 | value_base(); 18 | value_base( const value_base& ); 19 | ~value_base(); 20 | 21 | bool is_array()const; 22 | bool is_function()const; 23 | size_t size()const; 24 | 25 | /** 26 | * If a struct, iterates over fields 27 | * If a map, over keys 28 | * if an array, over indexes 29 | */ 30 | iterator begin(); 31 | const_iterator begin()const; 32 | iterator end(); 33 | const_iterator end()const; 34 | 35 | /** 36 | * If a function, calls it... 37 | */ 38 | value operator()()const; 39 | value operator()(); 40 | 41 | template 42 | value operator()(P1)const; 43 | template 44 | value operator()(P1); 45 | 46 | template 47 | value operator()(P1,P2)const; 48 | template 49 | value operator()(P1,P2); 50 | 51 | 52 | const char* type()const; 53 | 54 | void visit( read_value_visitor&& v )const; 55 | void visit( write_value_visitor&& v ); 56 | 57 | template 58 | T as()const; 59 | 60 | template 61 | void set_as( const T&& ); 62 | 63 | bool operator!()const; 64 | 65 | template 66 | inline T& get(); 67 | 68 | template 69 | inline const T& get()const; 70 | 71 | template 72 | inline const T* ptr()const; 73 | 74 | template 75 | inline T* ptr(); 76 | 77 | bool has_field( const std::string& field )const; 78 | 79 | protected: 80 | friend class value; 81 | friend class value_ref; 82 | friend class value_cref; 83 | inline const detail::place_holder* get_holder()const; 84 | inline detail::place_holder* get_holder(); 85 | 86 | char held[3*sizeof(void*)]; 87 | }; 88 | 89 | } } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /include/boost/reflect/value_cref.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_VALUE_CREF_HPP_ 2 | #define _BOOST_REFLECT_VALUE_CREF_HPP_ 3 | #include 4 | 5 | namespace boost { namespace reflect { 6 | 7 | /** 8 | * value ref has reference semantics, therefore it may only be 9 | * assigned to reference types at construction 10 | */ 11 | class value_cref : public value_base { 12 | public: 13 | template value_cref( const T& v ); 14 | template value_cref( const T&& t ); 15 | value_cref( const struct value& t ); 16 | 17 | value_cref( const value_cref& c ); 18 | value_cref( value_cref&& t ); 19 | 20 | /** 21 | * Return a field on this type as defined by BOOST_REFLECT() 22 | * macro. 23 | */ 24 | value_cref operator[]( const std::string& field )const; 25 | 26 | template 27 | inline const T& get()const; 28 | 29 | template 30 | inline const T* const_ptr()const; 31 | private: 32 | friend class value; 33 | 34 | template 35 | inline T& get(); 36 | 37 | template 38 | inline T* ptr(); 39 | 40 | using value_base::get; 41 | using value_base::ptr; 42 | using value_base::set_as; 43 | 44 | value_cref(){}; 45 | 46 | /** Cannot modify const ref */ 47 | template 48 | void set_as(const T&&); 49 | 50 | template 51 | value_cref operator = (T){ return *this; } 52 | value_cref operator = ( const value_cref& v ); 53 | }; 54 | 55 | 56 | } } // namespace boost 57 | 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/boost/reflect/value_ref.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_VALUE_REF_HPP_ 2 | #define _BOOST_REFLECT_VALUE_REF_HPP_ 3 | #include 4 | 5 | namespace boost { namespace reflect { 6 | 7 | /** 8 | * value ref has reference semantics, therefore it may only be 9 | * assigned to reference types at construction 10 | */ 11 | class value_ref : public value_base { 12 | 13 | public: 14 | template 15 | value_ref( T& v ); 16 | value_ref( const value_ref& ); 17 | value_ref( value_ref&& ); 18 | 19 | operator value_cref()const; 20 | value_cref operator[]( const std::string& field )const; 21 | value_ref operator[]( const std::string& field ); 22 | 23 | template 24 | value_ref& operator=( const T& r ); 25 | 26 | private: 27 | friend class value; 28 | // references must be provided a value at construction 29 | value_ref(){} 30 | value_ref(const class value_cref& ){} 31 | value_ref(const class value& ){} 32 | 33 | // you cannot assign references after construction 34 | template 35 | value_ref operator = (T){ return *this; } 36 | value_ref operator = ( const value_ref& v ); 37 | 38 | // const ref types need not apply 39 | template 40 | value_ref( const T& ); 41 | }; 42 | 43 | 44 | } } // namespace boost 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/boost/reflect/value_visitor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _BOOST_REFLECT_VALUE_VISITOR_HPP_ 2 | #define _BOOST_REFLECT_VALUE_VISITOR_HPP_ 3 | #include 4 | #include 5 | #include 6 | 7 | namespace boost { namespace reflect { 8 | class value_cref; 9 | class value_ref; 10 | struct read_value_visitor { 11 | virtual ~read_value_visitor(){} 12 | template 13 | void operator()( const T& s ){ (*this)(value_cref(s)); } 14 | 15 | virtual void operator()(){} 16 | virtual void operator()( const value_cref& s ){} 17 | virtual void operator()( const std::string& s ){} 18 | virtual void operator()( const uint64_t& s ){} 19 | virtual void operator()( const int64_t& s ){} 20 | virtual void operator()( const uint32_t& s ){} 21 | virtual void operator()( const int32_t& s ){} 22 | virtual void operator()( const uint16_t& s ){} 23 | virtual void operator()( const int16_t& s ){} 24 | virtual void operator()( const uint8_t& s ){} 25 | virtual void operator()( const int8_t& s ){} 26 | virtual void operator()( const double& s ){} 27 | virtual void operator()( const float& s ){} 28 | virtual void operator()( const bool& s ){} 29 | }; 30 | 31 | struct write_value_visitor { 32 | virtual ~write_value_visitor(){} 33 | template 34 | void operator()( T& s ){ value_ref vr(s); (*this)(vr); } 35 | 36 | virtual void operator()(){} 37 | virtual void operator()( value_ref& v ){} 38 | virtual void operator()( std::string& s ){} 39 | virtual void operator()( uint64_t& s ){} 40 | virtual void operator()( int64_t& s ){} 41 | virtual void operator()( uint32_t& s ){} 42 | virtual void operator()( int32_t& s ){} 43 | virtual void operator()( uint16_t& s ){}; 44 | virtual void operator()( int16_t& s ){} 45 | virtual void operator()( uint8_t& s ){} 46 | virtual void operator()( int8_t& s ){} 47 | virtual void operator()( double& s ){} 48 | virtual void operator()( float& s ){} 49 | virtual void operator()( bool& s ){} 50 | }; 51 | 52 | template 53 | struct get_visitor : read_value_visitor { 54 | T& m_val; 55 | get_visitor( T& v ):m_val(v){} 56 | virtual void operator()( const std::string& s ) { m_val = boost::lexical_cast(s); } 57 | virtual void operator()( const uint64_t& s ) { m_val = boost::lexical_cast(s); } 58 | virtual void operator()( const int64_t& s ) { m_val = boost::lexical_cast(s); } 59 | virtual void operator()( const uint32_t& s ) { m_val = boost::lexical_cast(s); } 60 | virtual void operator()( const int32_t& s ) { m_val = boost::lexical_cast(s); } 61 | virtual void operator()( const uint16_t& s ) { m_val = boost::lexical_cast(s); } 62 | virtual void operator()( const int16_t& s ) { m_val = boost::lexical_cast(s); } 63 | virtual void operator()( const uint8_t& s ) { m_val = boost::lexical_cast(s); } 64 | virtual void operator()( const int8_t& s ) { m_val = boost::lexical_cast(s); } 65 | virtual void operator()( const double& s ) { m_val = boost::lexical_cast(s); } 66 | virtual void operator()( const float& s ) { m_val = boost::lexical_cast(s); } 67 | virtual void operator()( const bool& s ) { m_val = boost::lexical_cast(s); } 68 | }; 69 | 70 | template 71 | struct set_visitor : write_value_visitor { 72 | const T& m_val; 73 | set_visitor( const T& v ):m_val(v){} 74 | 75 | virtual void operator()( std::string& s ) { s = boost::lexical_cast(m_val); } 76 | virtual void operator()( uint64_t& s ) { s = boost::lexical_cast(m_val); } 77 | virtual void operator()( int64_t& s ) { s = boost::lexical_cast(m_val); } 78 | virtual void operator()( uint32_t& s ) { s = boost::lexical_cast(m_val); } 79 | virtual void operator()( int32_t& s ) { s = boost::lexical_cast(m_val); } 80 | virtual void operator()( uint16_t& s ) { s = boost::lexical_cast(m_val); } 81 | virtual void operator()( int16_t& s ) { s = boost::lexical_cast(m_val); } 82 | virtual void operator()( uint8_t& s ) { s = boost::lexical_cast(m_val); } 83 | virtual void operator()( int8_t& s ) { s = boost::lexical_cast(m_val); } 84 | virtual void operator()( double& s ) { s = boost::lexical_cast(m_val); } 85 | virtual void operator()( float& s ) { s = boost::lexical_cast(m_val); } 86 | virtual void operator()( bool& s ) { s = boost::lexical_cast(m_val); } 87 | }; 88 | 89 | 90 | } } 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /include/boost/reflect/void.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __BOOST_REFLECT_VOID_HPP 2 | #define __BOOST_REFLECT_VOID_HPP 3 | #include 4 | 5 | namespace boost { namespace reflect { 6 | /** 7 | * @brief A type to replace void in generic code. 8 | * 9 | * void cannot be treated like any other type and thus always introduces 10 | * many 'special cases' to generic code. This type is used in generic code any 11 | * all functors that return void can be adapted to return void_t before being 12 | * used with generic code via boost::reflect::adapt_void. 13 | */ 14 | struct void_t{ 15 | friend std::ostream& operator<<(std::ostream& os,const void_t&) {return os;} 16 | friend std::istream& operator>>(std::istream& is,void_t&) {return is;} 17 | }; 18 | 19 | /** 20 | * @brief Converts functors returning void to functors returning \link 21 | boost::refelct::void_t void_t \link 22 | 23 | * Generic code that deals with functions returning void is a special case 24 | * that requires many work arounds. This class adapts a void(FusionSeq) functor 25 | * into a void_t(FusionSeq) functor. 26 | */ 27 | template 28 | struct adapt_void { 29 | typedef R result_type; 30 | 31 | adapt_void( const Functor _f):f(_f){} 32 | 33 | template 34 | result_type operator()( const Seq& seq )const { 35 | return f(seq); 36 | } 37 | template 38 | result_type operator()( Seq& seq )const { 39 | return f(seq); 40 | } 41 | Functor f; 42 | }; 43 | #ifndef DOXYGEN 44 | template 45 | struct adapt_void { 46 | typedef void_t result_type; 47 | adapt_void( const Functor _f):f(_f){} 48 | 49 | template 50 | result_type operator()( const Seq& seq )const { 51 | f(seq); return result_type(); 52 | } 53 | template 54 | result_type operator()( Seq& seq )const { 55 | f(seq); return result_type(); 56 | } 57 | Functor f; 58 | }; 59 | #endif 60 | } } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/boost/reflect/vtable.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file reflect.hpp 3 | * 4 | * This class defines the macros and types used to implement 5 | * an REFLECT interface. 6 | * 7 | */ 8 | #ifndef _BOOST_REFLECT_VTABLE_HPP_ 9 | #define _BOOST_REFLECT_VTABLE_HPP_ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | namespace boost { namespace reflect { 26 | 27 | struct mirror_interface; 28 | 29 | 30 | /** 31 | * @brief Contains functors defined by InterfaceDelegate for each reflected member of InterfaceType 32 | * 33 | * Use the @ref BOOST_REFLECT_ANY(NAME,MEMBERS) or BOOST_REFLECT_ANY_DERIVED(NAME,BASES,MEMBERS) to define the vtable for your 34 | * type. 35 | */ 36 | template 37 | class vtable {}; 38 | 39 | /** 40 | * @brief Enables specialization of visit for InterfaceType 41 | * 42 | * This class is specialized by BOOST_REFLECT_ANY and BOOST_REFLECT_ANY_DERIVED 43 | */ 44 | template 45 | struct vtable_reflector { 46 | template 47 | static void visit( const boost::reflect::vtable* vtbl, const Visitor& v ) {} 48 | }; 49 | 50 | #ifndef DOXYGEN 51 | template 52 | class vtable_base{}; 53 | #endif 54 | 55 | } } // namespace boost::reflect 56 | 57 | #ifndef DOXYGEN 58 | #define BOOST_REFLECT_VTABLE_PUBLIC_BASE( r, data, elem ) boost::reflect::vtable, 59 | 60 | #define BOOST_REFLECT_VTABLE_DEFINE_MEMBER( r, data, elem ) \ 61 | struct BOOST_PP_CAT( __reflect__, elem) : \ 62 | public InterfaceDelegate::template calculate_type::type \ 63 | { \ 64 | typedef typename InterfaceDelegate::template calculate_type::type base_type; \ 65 | using base_type::operator=;\ 66 | static const char* name() { return BOOST_PP_STRINGIZE(data); } \ 67 | template \ 68 | static void get_member_ptr( AssignType v ) { v = &Type::elem; } \ 69 | } elem; 70 | 71 | 72 | #define BOOST_REFLECT_VTABLE_VISIT_BASE( r, visitor, name ) \ 73 | vtable_reflector::visit( (const boost::reflect::vtable*)vtbl, visitor ); 74 | 75 | #define BOOST_REFLECT_VTABLE_VISIT_MEMBER( r, visitor, elem ) \ 76 | visitor.template operator()( BOOST_PP_STRINGIZE(elem) ); 77 | 78 | //visitor.template operator()( BOOST_PP_STRINGIZE(elem) ); 79 | 80 | // example of how to convert enumerate any BOOST_PP_SEQ, including BOOST_PP_SEQ_NIL 81 | #define BOOST_REFLECT_SEQ_ENUM(X) \ 82 | BOOST_PP_LIST_ENUM( \ 83 | BOOST_PP_LIST_REST( \ 84 | BOOST_PP_TUPLE_TO_LIST( BOOST_PP_INC(BOOST_PP_SEQ_SIZE(X)), BOOST_PP_SEQ_TO_TUPLE( \ 85 | BOOST_PP_SEQ_TRANSFORM( BOOST_REFLECT_VTABLE_PUBLIC_BASE, InterfaceDelegate, BOOST_PP_SEQ_PUSH_FRONT(X,(null)) ) ) ) \ 86 | ) \ 87 | ) 88 | 89 | #endif 90 | 91 | #define BOOST_REFLECT_ANY_DERIVED( NAME, INHERITS, MEMBERS ) \ 92 | BOOST_REFLECT_TYPEINFO(NAME) \ 93 | namespace boost { namespace reflect { \ 94 | template \ 95 | struct vtable : BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VTABLE_PUBLIC_BASE, InterfaceDelegate, INHERITS ) private vtable_base { \ 96 | typedef NAME interface_type; \ 97 | BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VTABLE_DEFINE_MEMBER, NAME, MEMBERS ) \ 98 | }; \ 99 | template<> struct vtable_reflector { \ 100 | typedef NAME interface_type; \ 101 | template \ 102 | static void visit( const boost::reflect::vtable* vtbl, \ 103 | const Visitor& visitor ) { \ 104 | typedef boost::reflect::vtable vtable_type; \ 105 | BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VTABLE_VISIT_BASE, visitor, INHERITS ) \ 106 | BOOST_PP_SEQ_FOR_EACH( BOOST_REFLECT_VTABLE_VISIT_MEMBER, visitor, MEMBERS ) \ 107 | } \ 108 | };\ 109 | \ 110 | } } 111 | 112 | #define BOOST_REFLECT_ANY( NAME, MEMBERS ) \ 113 | BOOST_REFLECT_ANY_DERIVED( NAME, BOOST_PP_SEQ_NIL, MEMBERS ) 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( ../include ) 2 | include_directories( ../../atomic/include ) 3 | include_directories( ../../cmt/include ) 4 | include_directories( ../../move/include ) 5 | SET( libraries 6 | #/usr/local/lib/tcmalloc/libtcmalloc.a 7 | boost_cmt 8 | boost_context 9 | ${Boost_THREAD_LIBRARY} 10 | ${Boost_ASIO_LIBRARY} 11 | ${Boost_SYSTEM_LIBRARY} 12 | ${Boost_SIGNALS_LIBRARY}) 13 | 14 | add_executable( value_test value_test.cpp ) 15 | target_link_libraries( value_test ${libraries} ) 16 | add_executable( value_function value_function.cpp ) 17 | target_link_libraries( value_test ${libraries} ) 18 | -------------------------------------------------------------------------------- /tests/value_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct to_json_visitor : public boost::reflect::read_value_visitor { 9 | std::ostream& os; 10 | to_json_visitor( const to_json_visitor& v ):os(v.os){} 11 | to_json_visitor( std::ostream& v ):os(v){} 12 | virtual void operator()( const boost::reflect::value_cref& s ) { 13 | if( s.is_array() ) { 14 | os<<'['; 15 | boost::reflect::const_iterator itr = s.begin(); 16 | if( itr != s.end() ) 17 | while( true ) { 18 | itr.value().visit(to_json_visitor(os)); 19 | ++itr; 20 | if( itr == s.end() ) 21 | break; 22 | else { os<<","; } 23 | } 24 | os<<']'; 25 | } else { 26 | os<<'{'; 27 | boost::reflect::const_iterator itr = s.begin(); 28 | if( itr != s.end() ) 29 | while( true ) { 30 | os << '"'<< itr.key() <<"\":"; 31 | itr.value().visit(to_json_visitor(os)); 32 | ++itr; 33 | if( itr == s.end() ) 34 | break; 35 | else { os<<","; } 36 | } 37 | os<<'}'; 38 | } 39 | } 40 | virtual void operator()( const std::string& s ) { os << '"'<(m.b)),sub(std::forward(m.sub)) 69 | ,data(std::forward >(m.data) ){ 70 | slog( "test(move)"); 71 | } 72 | 73 | test( const test& c ) 74 | :a(c.a),b(c.b){ slog("test(copy)"); ++test_count; } 75 | 76 | ~test() { slog( "~test" ); --test_count; } 77 | 78 | int a; 79 | std::string b; 80 | sub_val sub; 81 | std::vector data; 82 | }; 83 | BOOST_REFLECT( test, (a)(b)(sub)(data) ) 84 | 85 | using namespace boost::reflect; 86 | 87 | 88 | template 89 | void print_fields( const ValueType& t ) { 90 | t.visit( to_json_visitor(std::cout) ); 91 | /* 92 | slog( "printing fields: %1%", t.size() ); 93 | boost::reflect::const_iterator itr = t.begin(); 94 | while( itr != t.end() ) { 95 | slog( "%3% %1% = %2%", itr.key(), itr.value().as(), itr.value().type() ); 96 | ++itr; 97 | } 98 | */ 99 | } 100 | void test_seq() { 101 | value v(boost::fusion::make_vector( std::string("sequence str"), test( 5, "seq test" ) ) ); 102 | print_fields(v); 103 | } 104 | 105 | void test_stdmap() { 106 | elog( "stdmap test" ); 107 | std::map map_test; 108 | map_test["hello"] = test( 1, "world" ); 109 | map_test["goodbye"] = test( 2, "cruel world" ); 110 | 111 | value_cref mv(map_test); 112 | slog( "hello.b = %1%", mv["hello"]["b"].as() ); 113 | slog( "goodbye.b = %1%", mv["goodbye"]["b"].as() ); 114 | 115 | value_ref mvr(map_test); 116 | slog( "hello.b = %1%", mv["hello"]["b"].as() ); 117 | slog( "goodbye.b = %1%", mv["goodbye"]["b"].as() ); 118 | 119 | mvr["new_field"]["b"].set_as("Howdy Partner"); 120 | slog( "new_field.b = %1%", mv["new_field"]["b"].as() ); 121 | slog( "new_field.b = %1%", mvr["new_field"]["b"].as() ); 122 | 123 | map_test["hello"].data.push_back( sub_val( "win", 8.8 ) ); 124 | map_test["hello"].data.push_back( sub_val( "lose", 4.4 ) ); 125 | print_fields(mv["hello"]); 126 | slog( "printing map fields now\n" ); 127 | print_fields(mv); 128 | } 129 | 130 | 131 | void test_sub() { 132 | test t(1,"test_ref"); 133 | t.sub.happy = "oh happy pie day"; 134 | t.sub.day = 3.1416; 135 | 136 | value_cref v(t); 137 | 138 | BOOST_ASSERT( v["sub"]["happy"].as() == "oh happy pie day" ); 139 | print_fields( value_ref(t.sub) ); 140 | print_fields( value_cref(t.sub) ); 141 | print_fields( value(t.sub) ); 142 | } 143 | 144 | void test_ref() { 145 | slog( "testing value_ref...." ); 146 | test t(1,"test_ref"); 147 | //value_ref not_empty; // should not compile! 148 | 149 | 150 | value_ref v(t); 151 | 152 | //v = t; // should not compile because reference must be asigned at construction 153 | BOOST_ASSERT( v["a"].as() == 1 ); 154 | BOOST_ASSERT( v["a"].as() == std::string("1") ); 155 | bool threw = false; 156 | try { 157 | v["b"].as(); 158 | } catch ( std::bad_cast& ) { 159 | threw = true; 160 | } 161 | BOOST_ASSERT(threw); 162 | 163 | v["b"].set_as(2); 164 | 165 | try { 166 | BOOST_ASSERT( 2 == v["b"].as() ); 167 | } catch ( std::bad_cast& ) { 168 | BOOST_ASSERT( !threw ); 169 | } 170 | 171 | BOOST_ASSERT( v["b"].as() == std::string("2") ); 172 | BOOST_ASSERT( t.b == v["b"].as() ); 173 | } 174 | 175 | void test_cref() { 176 | slog( "testing value_cref...." ); 177 | test t(1,"test_cref"); 178 | value_cref v(t); 179 | BOOST_ASSERT( v["a"].as() == 1 ); 180 | BOOST_ASSERT( v["a"].as() == std::string("1") ); 181 | bool threw = false; 182 | try { 183 | v["b"].as(); 184 | } catch ( std::bad_cast& ) { 185 | threw = true; 186 | } 187 | BOOST_ASSERT(threw); 188 | 189 | //v["b"].set_as(2); // this should not compile... 190 | 191 | BOOST_ASSERT( v["b"].as() == std::string("test_cref") ); 192 | } 193 | 194 | void test_ref_to_cref() { 195 | 196 | } 197 | 198 | void test_val() { 199 | slog( "testing value...." ); 200 | test t(1,"test_val"); 201 | value v(t); 202 | BOOST_ASSERT( v["a"].as() == 1 ); 203 | BOOST_ASSERT( v["a"].as() == std::string("1") ); 204 | BOOST_ASSERT( v["b"].as() == std::string("test_val") ); 205 | bool threw = false; 206 | try { 207 | v["b"].as(); 208 | } catch ( std::bad_cast& ) { 209 | threw = true; 210 | } 211 | BOOST_ASSERT(threw); 212 | 213 | v["b"].set_as(2); 214 | 215 | try { 216 | BOOST_ASSERT( 2 == v["b"].as() ); 217 | } catch ( std::bad_cast& ) { 218 | BOOST_ASSERT( !threw ); 219 | } 220 | 221 | BOOST_ASSERT( v["b"].as() == std::string("2") ); 222 | BOOST_ASSERT( t.b != v["b"].as() ); 223 | 224 | value v2(test(2,"test_val rval const 2")); 225 | BOOST_ASSERT( test_count == 3 ); 226 | const value_cref cr(v2); 227 | slog("%1% =? %2%", cr.const_ptr(), v2.ptr() ); 228 | cr["a"]; 229 | BOOST_ASSERT( v2["a"].ptr() == cr["a"].const_ptr() ); 230 | v2["a"].set_as(55); 231 | BOOST_ASSERT( v2["a"].as() == cr["a"].as() ); 232 | 233 | 234 | } 235 | 236 | 237 | 238 | int main( int argc, char** argv ) { 239 | try { 240 | test_ref(); 241 | BOOST_ASSERT( &test_ref&& (test_count == 0) ); 242 | test_cref(); 243 | BOOST_ASSERT( &test_cref&& (test_count == 0) ); 244 | test_ref_to_cref(); 245 | BOOST_ASSERT( &test_ref_to_cref&& (test_count == 0) ); 246 | test_val(); 247 | BOOST_ASSERT( &test_val&& (test_count == 0) ); 248 | wlog( "test sub!" ); 249 | test_sub(); 250 | BOOST_ASSERT( &test_val&& (test_count == 0) ); 251 | test_stdmap(); 252 | wlog( "testing sequence" ); 253 | test_seq(); 254 | } catch ( const boost::exception& e ) { 255 | elog( "%1%", boost::diagnostic_information(e) ); 256 | } 257 | return 0; 258 | } 259 | --------------------------------------------------------------------------------