├── LICENSE ├── Makefile ├── README.md ├── reflection++ ├── accessor.hpp ├── accessor_infer.hpp ├── holder.hpp ├── meta.hpp ├── static_str.hpp ├── traits.hpp ├── utility.hpp ├── visitor.hpp ├── visitor │ ├── basic.hpp │ ├── bson.hpp │ ├── bson_view.hpp │ ├── json.hpp │ ├── mysql.hpp │ └── strtree.hpp └── visitor_chain.hpp └── tests ├── common.hpp ├── main.cpp ├── main_dup.cpp ├── meta.cpp ├── static_str.cpp ├── visitor_bson.cpp ├── visitor_chain.cpp ├── visitor_json.cpp └── visitor_strtree.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 hcz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = clang++ 2 | 3 | FLAGS = -Wall -Wextra -pedantic -ferror-limit=1 -std=c++11 -O0 -g 4 | 5 | CFLAGS = `pkg-config --cflags libbsoncxx` 6 | LFLAGS = `pkg-config --libs libbsoncxx` 7 | 8 | NM = nm 9 | 10 | NMFLAGS = -C -l -p -S 11 | 12 | CAT = less 13 | 14 | HPP_COMMON = $(wildcard reflection++/*.hpp) 15 | HPP_VISITOR = $(wildcard reflection++/visitor/*.hpp) 16 | HPP_TESTS = tests/common.hpp 17 | CPP_MAIN = tests/main.cpp 18 | CPP_TESTS = $(wildcard tests/*.cpp) 19 | 20 | default: 21 | echo "make test\nmake pp\nmake nm\nmake clean" 22 | 23 | tests.out: $(HPP_COMMON) $(HPP_VISITOR) $(HPP_TESTS) $(CPP_TESTS) 24 | $(CC) $(FLAGS) $(CFLAGS) $(LFLAGS) $(CPP_TESTS) -o $@ 25 | 26 | main.cpp.out: $(HPP_COMMON) $(HPP_VISITOR) $(HPP_TESTS) $(CPP_TESTS) 27 | $(CC) -E $(FLAGS) $(CFLAGS) $(CPP_MAIN) -o $@ 28 | 29 | names.nm.out: tests.out 30 | $(NM) $(NMFLAGS) $< > $@ 31 | 32 | test: tests.out 33 | ./$< 34 | 35 | pp: main.cpp.out 36 | $(CAT) $< 37 | 38 | nm: names.nm.out 39 | $(CAT) $< 40 | 41 | clean: 42 | touch rm_placeholder.out 43 | rm *.out 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Reflection++ 2 | === 3 | 4 | Yet another (?) header-only C++11 reflection library. 5 | 6 | Usage 7 | --- 8 | 9 | Add meta information to an object: 10 | 11 | struct TestStruct { 12 | int member1; 13 | float member2; 14 | }; 15 | RPP_TYPE_OBJECT( 16 | __(member1) 17 | __(member2), 18 | TestStruct 19 | ) 20 | 21 | Add meta information to an STL container: 22 | 23 | template 24 | RPP_TYPE_DYNAMIC_GENERIC(T, std::vector) 25 | 26 | Create a visitor: 27 | 28 | struct Visitor: public VisitorBase<> { 29 | void visit(int &value) { 30 | std::cerr << "int(" << value << ") "; 31 | } 32 | 33 | void visit(float &value) { 34 | std::cerr << "float(" << value << ") "; 35 | } 36 | 37 | template 38 | void operator()(AccessorSimple &accessor) { 39 | visit(accessor()); 40 | } 41 | 42 | template 43 | void operator()(AccessorObject &accessor) { 44 | std::cerr << "object( "; 45 | 46 | for (rpp_size_t i = 0; i < accessor.size(); ++i) { 47 | accessor.doMemberVisit(*this, i); 48 | } 49 | 50 | std::cerr << ") "; 51 | } 52 | }; 53 | 54 | Register the visitor and list all visitors: 55 | 56 | RPP_VISITOR_REG(Visitor) 57 | RPP_VISITOR_COLLECT(VisitorAll) 58 | 59 | Add meta information to a variable: 60 | 61 | TestStruct s{2, 3.5}; 62 | RPP_META_REF(s, VisitorAll) m; 63 | 64 | Visit the variable: 65 | 66 | Visitor v; 67 | m.doVisit(v); 68 | 69 | Build 70 | --- 71 | 72 | Compile it like this: 73 | 74 | clang++ -std=c++11 your_code.cpp 75 | 76 | If you want to use the BSON visitor, [bson-cxx](https://github.com/mongodb/mongo-cxx-driver) is required. 77 | -------------------------------------------------------------------------------- /reflection++/accessor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "holder.hpp" 4 | 5 | namespace rpp { 6 | 7 | // to construct accessors as a member of object 8 | template 9 | struct AccessorFactory { 10 | // static only 11 | AccessorFactory() = delete; 12 | 13 | template 14 | static auto make(Object &) -> decltype(Accessor{}) { 15 | return Accessor{}; 16 | } 17 | 18 | template 19 | static auto make(Object &object) -> decltype(Accessor{object}) { 20 | return Accessor{object}; 21 | } 22 | }; 23 | 24 | // data accessors of simple data 25 | template 26 | struct AccessorSimple: public Value { 27 | using Value::Value; 28 | 29 | using Type = AccessorSimple< 30 | HolderType> 31 | >; 32 | }; 33 | 34 | // helper class of AccessObject 35 | // add information of object members to an accessor 36 | template 37 | struct AccessorObjectHelper; 38 | 39 | template 40 | struct AccessorObjectHelper< 41 | Value, TypeList<> 42 | >: public Value { 43 | using Value::Value; 44 | 45 | using MemberTypes = TypeList<>; 46 | 47 | rpp_size_t size() { 48 | return 0; 49 | } 50 | 51 | const char *getMemberName(rpp_size_t) { 52 | throw Exception{}; 53 | } 54 | 55 | template 56 | typename Visitor::ReturnType doMemberVisit(Visitor &, rpp_size_t) { 57 | throw Exception{}; 58 | } 59 | }; 60 | 61 | template 62 | struct AccessorObjectHelper< 63 | Value, TypeList 64 | >: public AccessorObjectHelper> { 65 | using AccessorObjectHelper>::AccessorObjectHelper; 66 | 67 | using MemberTypes = typename AccessorObjectHelper> 68 | ::MemberTypes 69 | ::template Push 70 | ::template Push; 71 | 72 | rpp_size_t size() { 73 | return 1 + AccessorObjectHelper>::size(); 74 | } 75 | 76 | const char *getMemberName(rpp_size_t index) { 77 | if (index == 0) { 78 | // notice: Name is a holder object 79 | return AccessorFactory::make((*this)())(); 80 | } else { 81 | return AccessorObjectHelper> 82 | ::getMemberName(index - 1); 83 | } 84 | } 85 | 86 | template 87 | typename Visitor::ReturnType doMemberVisit(Visitor &visitor, rpp_size_t index) { 88 | if (index == 0) { 89 | // notice: can not use universal init here 90 | auto member = AccessorFactory::make((*this)()); 91 | 92 | return visitor(member); 93 | } else { 94 | return AccessorObjectHelper> 95 | ::template doMemberVisit(visitor, index - 1); 96 | } 97 | } 98 | }; 99 | 100 | // data accessors associated with members 101 | template 102 | struct AccessorObject: public AccessorObjectHelper { 103 | using AccessorObjectHelper::AccessorObjectHelper; 104 | 105 | using Type = AccessorObject< 106 | HolderType>, 107 | typename AccessorObjectHelper::MemberTypes 108 | >; 109 | }; 110 | 111 | // data accessors associated with dynamic members 112 | template 113 | struct AccessorDynamic: public Value { 114 | using Value::Value; 115 | 116 | using Type = AccessorDynamic< 117 | HolderType>, 118 | typename Member::Type 119 | >; 120 | 121 | template 122 | typename Visitor::ReturnType doMemberVisit(Visitor &visitor, T &value) { 123 | auto member = AccessorFactory::make(value); 124 | 125 | return visitor(member); 126 | } 127 | }; 128 | 129 | } 130 | -------------------------------------------------------------------------------- /reflection++/accessor_infer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "accessor.hpp" 4 | 5 | namespace rpp { 6 | 7 | // a compile-time wraper class of AccessorSimple 8 | template 9 | struct AccessorSimpleWrap { 10 | template 11 | using Accessor = AccessorSimple; 12 | 13 | // compile-time only 14 | AccessorSimpleWrap() = delete; 15 | }; 16 | 17 | // a compile-time wraper class of AccessorObject 18 | template 19 | struct AccessorObjectWrap { 20 | using List = Members; 21 | 22 | template 23 | using Accessor = AccessorObject; 24 | 25 | // compile-time only 26 | AccessorObjectWrap() = delete; 27 | }; 28 | 29 | // a compile-time wraper class of AccessorDynamic 30 | template 31 | struct AccessorDynamicWrap { 32 | template 33 | using Accessor = AccessorDynamic; 34 | 35 | // compile-time only 36 | AccessorDynamicWrap() = delete; 37 | }; 38 | 39 | // get the default accessor 40 | #define RPP_ACCESSOR(Value) \ 41 | typename AccessorInfer< \ 42 | rpp::GetReturn \ 43 | >::template Accessor 44 | 45 | // get the default accessor, bind the holder's type 46 | #define RPP_ACCESSOR_AS(Mode, ...) \ 47 | RPP_ACCESSOR(RPP_HOLDER_##Mode(__VA_ARGS__)) 48 | 49 | // enable AccessorInfer in the current namespace 50 | #define RPP_ACCESSOR_INFER_INIT() \ 51 | /* an abstract function to infer the default accessor of a type */ \ 52 | template \ 53 | struct AccessorInfer final: public rpp::AccessorSimpleWrap<> { \ 54 | /* compile-time only */ \ 55 | AccessorInfer() = delete; \ 56 | }; 57 | 58 | RPP_ACCESSOR_INFER_INIT() 59 | 60 | // helper macros begin 61 | 62 | // append an accessor to a TypeList 63 | #define RPP_ACCESSOR_APPEND_ACCESSOR(Object, Name, Accessor) \ 64 | ::Append::Append 65 | // append an accessor to a TypeList (using default accessors) 66 | // wrappers of RPP_ACCESSOR_AS 67 | // notice: LOCAL or DYNAMIC as member means type casting 68 | #define RPP_ACCESSOR_APPEND_TYPE(Object, Type) \ 69 | ::Append::Append 70 | #define RPP_ACCESSOR_APPEND_CONST(Object, Value) \ 71 | ::Append::Append 72 | #define RPP_ACCESSOR_APPEND_LOCAL(Object, Type) \ 73 | ::Append::Append 74 | #define RPP_ACCESSOR_APPEND_REF(Object, Value) \ 75 | ::Append::Append 76 | #define RPP_ACCESSOR_APPEND_DYNAMIC(Object, Type) \ 77 | ::Append::Append 78 | #define RPP_ACCESSOR_APPEND_MEMBER(Object, Value) \ 79 | ::Append::Append 80 | // append an accessor wraps a base type to a TypeList 81 | #define RPP_ACCESSOR_APPEND_BASE(Derived, Base) \ 82 | RPP_ACCESSOR_APPEND_DYNAMIC(Derived, Base) 83 | // append accessors of a base type (fetched from AccessorObjectWrap) to a TypeList 84 | #define RPP_ACCESSOR_APPEND_BASE_INLINE(Derived, Base) \ 85 | ::AppendList::List> 86 | 87 | // build a TypeList of accessors 88 | #define RPP_MEMBER_IMPL(Member, Mode, ...) \ 89 | , RPP_MEMBER_LIST), RPP_ACCESSOR_APPEND_##Mode, Member 90 | #define RPP_MEMBER_LIST_BEGIN(Object, Next) \ 91 | Next##_1(Object 92 | #define RPP_MEMBER_LIST_1(Object, Mode, Member, Next) \ 93 | Mode(Object, Member) Next##_2(Object 94 | #define RPP_MEMBER_LIST_2(Object, Mode, Member, Next) \ 95 | Mode(Object, Member) Next##_1(Object 96 | #define RPP_MEMBER_LIST_END_1(...) /* nothing */ 97 | #define RPP_MEMBER_LIST_END_2(...) /* nothing */ 98 | 99 | // helper macros end 100 | 101 | // define a member in RPP_TYPE_OBJECT 102 | #define RPP_MEMBER(...) \ 103 | RPP_MEMBER_IMPL(__VA_ARGS__, MEMBER, ) 104 | #ifndef __ 105 | #define __ RPP_MEMBER 106 | #endif 107 | 108 | // set the default accessor to AccessorObject and bind members 109 | #define RPP_TYPE_OBJECT(Members, Object) \ 110 | template <> \ 111 | struct AccessorInfer: public rpp::AccessorObjectWrap< \ 112 | rpp::TypeList<> \ 113 | RPP_MEMBER_LIST_BEGIN( \ 114 | Object \ 115 | Members \ 116 | , RPP_MEMBER_LIST_END) \ 117 | ) \ 118 | > {}; 119 | 120 | // set the default accessor to AccessorDynamic and bind the (abstract) member 121 | #define RPP_TYPE_DYNAMIC(Member, Object) \ 122 | template <> \ 123 | struct AccessorInfer: public rpp::AccessorDynamicWrap< \ 124 | RPP_ACCESSOR_AS(DYNAMIC, Member) \ 125 | > {}; 126 | 127 | // RPP_TYPE_OBJECT with template arguments 128 | // __VA_ARGS__ is the type of object 129 | #define RPP_TYPE_OBJECT_GENERIC(Members, ...) \ 130 | /* before the macro: template */ \ 131 | struct AccessorInfer>: public rpp::AccessorObjectWrap< \ 132 | rpp::TypeList<> \ 133 | RPP_MEMBER_LIST_BEGIN( \ 134 | RPP_PASS(__VA_ARGS__) \ 135 | Members \ 136 | , RPP_MEMBER_LIST_END) \ 137 | ) \ 138 | > {}; 139 | 140 | // RPP_TYPE_DYNAMIC with template arguments 141 | // __VA_ARGS__ is the type of object 142 | #define RPP_TYPE_DYNAMIC_GENERIC(Member, ...) \ 143 | /* before the macro: template */ \ 144 | struct AccessorInfer>: public rpp::AccessorDynamicWrap< \ 145 | RPP_ACCESSOR_AS(DYNAMIC, Member) \ 146 | > {}; 147 | 148 | } 149 | -------------------------------------------------------------------------------- /reflection++/holder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "traits.hpp" 4 | #include "static_str.hpp" 5 | 6 | namespace rpp { 7 | 8 | // data holders that hold types 9 | template 10 | struct HolderType { 11 | HolderType() {} 12 | 13 | const HolderType &operator()() { 14 | return *this; 15 | } 16 | }; 17 | 18 | // data holders that hold data as a static variable in a function 19 | // allow constant only 20 | template 21 | struct HolderConst { 22 | HolderConst() {} 23 | 24 | const T &operator()() { 25 | static const T value{_value}; 26 | 27 | return value; 28 | } 29 | }; 30 | 31 | // data holders that hold data by themselves 32 | template 33 | struct HolderLocal { 34 | T value; 35 | 36 | HolderLocal(T &&_value): value(static_cast(_value)) {} 37 | HolderLocal(const T &_value): value(_value) {} 38 | // HolderLocal(T &&_value): value{static_cast(_value)} {} 39 | // HolderLocal(const T &_value): value{_value} {} 40 | 41 | T &operator()() { 42 | return value; 43 | } 44 | }; 45 | 46 | // data holders point to a specified variable 47 | template 48 | struct HolderRef { 49 | HolderRef() {} 50 | 51 | T &operator()() { 52 | return value; 53 | } 54 | }; 55 | 56 | // data holders point to a run-time variable 57 | template 58 | struct HolderDynamic { 59 | T &value; 60 | 61 | HolderDynamic(T &_value): value{_value} {} 62 | 63 | T &operator()() { 64 | return value; 65 | } 66 | }; 67 | 68 | // data holders point to a specified member of a class 69 | template 70 | struct HolderMember { 71 | Object &object; 72 | 73 | HolderMember( 74 | Object &_object 75 | ): object{_object} {} 76 | 77 | T &operator()() { 78 | return object.*member; 79 | } 80 | }; 81 | 82 | // generate a holder type 83 | #define RPP_HOLDER_TYPE(...) \ 84 | rpp::HolderType<__VA_ARGS__> 85 | #define RPP_HOLDER_CONST(...) \ 86 | rpp::HolderConst 87 | #define RPP_HOLDER_STR(...) \ 88 | rpp::HolderConst 89 | #define RPP_HOLDER_LOCAL(...) \ 90 | rpp::HolderLocal<__VA_ARGS__> 91 | #define RPP_HOLDER_REF(...) \ 92 | rpp::HolderRef 93 | #define RPP_HOLDER_DYNAMIC(...) \ 94 | rpp::HolderDynamic<__VA_ARGS__> 95 | #define RPP_HOLDER_MEMBER(Object, ...) \ 96 | rpp::HolderMember< \ 97 | decltype(rpp::memberToObject(&Object::__VA_ARGS__)), \ 98 | decltype(Object::__VA_ARGS__), \ 99 | &Object::__VA_ARGS__ \ 100 | > 101 | 102 | } 103 | -------------------------------------------------------------------------------- /reflection++/meta.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "accessor_infer.hpp" 4 | 5 | namespace rpp { 6 | 7 | // the base class of meta information containers 8 | template 9 | struct MetaBase; 10 | 11 | template <> 12 | struct MetaBase< 13 | TypeList<> 14 | > { 15 | virtual const char *getName() = 0; 16 | 17 | // see: using MetaBase>::doVisit 18 | void doVisit() = delete; 19 | }; 20 | 21 | template 22 | struct MetaBase< 23 | TypeList 24 | >: public MetaBase> { 25 | using MetaBase>::doVisit; 26 | 27 | virtual typename Visitor::ReturnType doVisit(Visitor &visitor) = 0; 28 | }; 29 | 30 | // the implementation of MetaBase 31 | // implemented vitrual functions 32 | template > 33 | struct MetaImpl; 34 | 35 | template 36 | struct MetaImpl< 37 | Name, Accessor, TypeList<>, Base 38 | >: public Base, protected Name, protected Accessor { 39 | using Accessor::Accessor; 40 | using Base::doVisit; 41 | 42 | virtual const char *getName() override { 43 | return (*static_cast(this))(); 44 | } 45 | }; 46 | 47 | template 48 | struct MetaImpl< 49 | Name, Accessor, TypeList, Base 50 | >: public MetaImpl, Base> { 51 | using MetaImpl, Base>::MetaImpl; 52 | using MetaImpl, Base>::doVisit; 53 | 54 | virtual typename Visitor::ReturnType doVisit(Visitor &visitor) override { 55 | return visitor(*static_cast(this)); 56 | } 57 | }; 58 | 59 | // generate a meta info type 60 | // wrappers of RPP_ACCESSOR_AS 61 | #define RPP_META_TYPE(Type, ...) \ 62 | rpp::MetaImpl< \ 63 | RPP_HOLDER_STR(#Type), \ 64 | RPP_ACCESSOR_AS(TYPE, Type), \ 65 | __VA_ARGS__ \ 66 | > 67 | #define RPP_META_CONST(Value, ...) \ 68 | rpp::MetaImpl< \ 69 | RPP_HOLDER_STR(#Value), \ 70 | RPP_ACCESSOR_AS(CONST, Value), \ 71 | __VA_ARGS__ \ 72 | > 73 | #define RPP_META_LOCAL(Name, Type, ...) \ 74 | rpp::MetaImpl< \ 75 | RPP_HOLDER_STR(Name), \ 76 | RPP_ACCESSOR_AS(LOCAL, Type), \ 77 | __VA_ARGS__ \ 78 | > 79 | #define RPP_META_REF(Value, ...) \ 80 | rpp::MetaImpl< \ 81 | RPP_HOLDER_STR(#Value), \ 82 | RPP_ACCESSOR_AS(REF, Value), \ 83 | __VA_ARGS__ \ 84 | > 85 | #define RPP_META_DYNAMIC(Name, Type, ...) \ 86 | rpp::MetaImpl< \ 87 | RPP_HOLDER_STR(Name), \ 88 | RPP_ACCESSOR_AS(DYNAMIC, Type), \ 89 | __VA_ARGS__ \ 90 | > 91 | #define RPP_META_MEMBER(Object, Value, ...) \ 92 | rpp::MetaImpl< \ 93 | RPP_HOLDER_STR(#Value), \ 94 | RPP_ACCESSOR_AS(MEMBER, Object, Value), \ 95 | __VA_ARGS__ \ 96 | > 97 | 98 | } 99 | -------------------------------------------------------------------------------- /reflection++/static_str.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "utility.hpp" 4 | 5 | namespace rpp { 6 | 7 | constexpr rpp_size_t strLen(const char *str, rpp_size_t index = 0) { 8 | return str[index] == 0 ? index : strLen(str, index + 1); 9 | } 10 | 11 | constexpr char strIndex(const char *str, rpp_size_t index) { 12 | return index < strLen(str) ? str[index] : 0; 13 | } 14 | 15 | // a compile-time string 16 | template 17 | struct StaticStr final { 18 | template 19 | using Append = StaticStr; 20 | 21 | // compile-time only 22 | StaticStr() = delete; 23 | }; 24 | 25 | template 26 | struct StaticStr<0, c...> final { 27 | static const char str[]; 28 | 29 | template 30 | using Append = StaticStr<0, c...>; 31 | 32 | // compile-time only 33 | StaticStr() = delete; 34 | }; 35 | 36 | template 37 | const char StaticStr<0, c...>::str[]{c..., 0}; 38 | 39 | #define RPP_STATIC_STR(Str) \ 40 | ( \ 41 | rpp::StaticStr::Append \ 42 | ::Append::Append \ 43 | ::Append::Append \ 44 | ::Append::Append \ 45 | ::Append::Append \ 46 | ::Append::Append \ 47 | ::Append::Append \ 48 | ::Append::Append \ 49 | ::Append::Append \ 50 | ::Append::Append \ 51 | ::Append::Append \ 52 | ::Append::Append \ 53 | ::Append::Append \ 54 | ::Append::Append \ 55 | ::Append::Append \ 56 | ::Append::Append \ 57 | ::Append::Append \ 58 | ::Append::Append \ 59 | ::Append::Append \ 60 | ::Append::Append \ 61 | ::Append::Append \ 62 | ::Append::Append \ 63 | ::Append::Append \ 64 | ::Append::Append \ 65 | ::Append::Append \ 66 | ::Append::Append \ 67 | ::Append::Append \ 68 | ::Append::Append \ 69 | ::Append::Append \ 70 | ::Append::Append \ 71 | ::Append::Append \ 72 | ::Append::Append \ 73 | ::str \ 74 | ) 75 | 76 | } 77 | -------------------------------------------------------------------------------- /reflection++/traits.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace rpp { 4 | 5 | // get a reference to a type 6 | template 7 | using GetRef = T &; 8 | 9 | // get the return type of a function 10 | template 11 | using GetReturn = decltype((*static_cast(nullptr))()); 12 | 13 | // generate an error if the value is not true 14 | template 15 | using Ensure = decltype(static_cast(sizeof(char [value ? 1 : -1]))); 16 | 17 | // get the actual object of a member pointer 18 | template 19 | Object memberToObject(T Object::*); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /reflection++/utility.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // TODO: include? 4 | #define RPP_EXCEPTION_PRINT 5 | #ifdef RPP_EXCEPTION_PRINT 6 | #include 7 | #endif 8 | 9 | namespace rpp { 10 | 11 | // type of size 12 | using rpp_size_t = unsigned long; 13 | 14 | // exception 15 | struct Exception { 16 | // TODO 17 | Exception() { 18 | // 19 | } 20 | 21 | Exception(const char *file, const rpp_size_t line, const char *func) { 22 | #ifdef RPP_EXCEPTION_PRINT 23 | std::cerr << "ERROR: " << file << ":" << line << " " << func << std::endl; 24 | #endif 25 | } 26 | }; 27 | 28 | // wrap a type (for macro arguments) 29 | #define RPP_PASS(...) \ 30 | decltype((static_cast __VA_ARGS__>(nullptr))()) 31 | 32 | // a compile-time type list to contain classes 33 | template 34 | struct TypeList final { 35 | template 36 | using Push = TypeList; 37 | 38 | template 39 | using Append = TypeList; 40 | 41 | template