From e97ba2d272cbf98af164a033d78f321345b0554c Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Wed, 17 Jul 2024 20:11:55 +0530 Subject: [PATCH 1/9] comments..Builder. --- ReflectionTemplateLib/builder/inc/Builder.h | 292 ++++++++++-------- ReflectionTemplateLib/builder/inc/Builder.hpp | 36 ++- 2 files changed, 189 insertions(+), 139 deletions(-) diff --git a/ReflectionTemplateLib/builder/inc/Builder.h b/ReflectionTemplateLib/builder/inc/Builder.h index 8612cacf..bba74b94 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.h +++ b/ReflectionTemplateLib/builder/inc/Builder.h @@ -5,133 +5,177 @@ namespace rtl { - namespace builder - { - template - struct Builder; - } - - - namespace builder - { - template<> - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(*pFunctor)()) const; + namespace builder + { + /* Provides interface to register all sort of functions, methods & constructors. + _signature: arguments types of the functions/constructors. + _typeQ: Builder, specialized with TypeQ, + TypeQ::None - provides interface to register non-member and static member funtions. + TypeQ::Mute - provides interface to register member funtion. + TypeQ::Const - provides interface to register const-member funtions. + Every builder specialization has a 'build()' function, which takes function pointer as + an argument which can be member(static/const)/non-member. + */ template + struct Builder; + } + + + namespace builder + { + /* specialized specifically to register overloaded non-member & static member functions with no arguments. + Objects of this class will be created & returned by these functions, + - Reflect::function(..) + - RecordBuilder<_recordType>::methodStatic(..) + with template parameter is only 'void', explicitly specified. + */ template<> + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(*pFunctor)()) const; + }; + + + /* specialized specifically to register overloaded non-member & static member functions with any arguments. + Objects of this class will be created & returned by these functions, + - Reflect::function<...>(..) + - RecordBuilder<_recordType>::methodStatic<...>(..) + with template parameters can be anything, explicitly specified. + */ template + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(*pFunctor)(_signature...)) const; + }; + + + /* specialized specifically to register non-member functions with any signature and with no overloads. + Objects of this class will be created & returned by these functions, + - Reflect::function(..) + - RecordBuilder<_recordType>::methodStatic(..) + with no template parameters specified. + */ template<> + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(*pFunctor)(_signature...)) const; + }; + } + + + namespace builder + { + /* specialized specifically to register overloaded const-member-functions with no arguments. + Objects of this class will be created & returned by function, + - RecordBuilder<_recordType>::methodConst(..) + with template parameters is only 'void' explicitly specified. + */ template<> + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)() const) const; }; - template - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(*pFunctor)(_signature...)) const; - }; - - - template<> - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(*pFunctor)(_signature...)) const; - }; - } - - - namespace builder - { - template<> - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)() const) const; - }; - - - template - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...) const) const; - }; - - - template<> - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)() const) const; - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...) const) const; - }; - } + /* specialized specifically to register overloaded const-member-functions with any arguments. + Objects of this class will be created & returned by function, + - RecordBuilder<_recordType>::methodConst<...>(..) + with template parameters can be anything, explicitly specified. + */ template + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...) const) const; + }; + + + /* specialized specifically to register non-overloaded const-member-functions with any arguments. + Objects of this class will be created & returned by function, + - RecordBuilder<_recordType>::methodConst() + with no template parameters specified. + */ template<> + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...) const) const; + }; + } - namespace builder - { - template<> - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)()) const; - }; - - - template - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; - }; - - - template<> - struct Builder : protected detail::ReflectionBuilder - { - Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - constexpr const access::Function - build(enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr) const; - - template - constexpr const access::Function - build(enable_if_same::HEAD > *_= nullptr) const; - - template - constexpr const access::Function - build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr, - enable_if_not_same::HEAD > *__= nullptr) const; - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; - }; - } + namespace builder + { + /* specialized specifically to register overloaded non-const-member-functions with no arguments. + Objects of this class will be created & returned by function, + - RecordBuilder<_recordType>::method(..) + with template parameters is only 'void' explicitly specified. + */ template<> + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)()) const; + }; + + + /* specialized specifically to register overloaded non-const-member-functions with no arguments. + Objects of this class will be created & returned by function, + - RecordBuilder<_recordType>::method(..) + with template parameters is only 'void' explicitly specified. + */ template + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; + }; + + + /* specialized specifically to register non-overloaded non-const-member-functions and constructors with any arguments. + Objects of this class will be created & returned by function, + - RecordBuilder<_recordType>::method() - with no template parameters specified. + - RecordBuilder<_recordType>::constructor<...>() - template parameters can be anything, explicitly specified. + */ template<> + struct Builder : protected detail::ReflectionBuilder + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function + build(enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr) const; + + template + constexpr const access::Function + build(enable_if_same::HEAD > *_= nullptr) const; + + template + constexpr const access::Function + build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr, + enable_if_not_same::HEAD > *__= nullptr) const; + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/Builder.hpp b/ReflectionTemplateLib/builder/inc/Builder.hpp index 8b54ce7e..272f08d4 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.hpp +++ b/ReflectionTemplateLib/builder/inc/Builder.hpp @@ -4,14 +4,16 @@ namespace rtl { - namespace builder - { - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } - - template + namespace builder + { + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } + + /* this build() will accept all non-member function pointer, even the ones with zero args (only + in absence of any other overloaded function) + */ template inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const { return buildFunctor(pFunctor); @@ -26,7 +28,11 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - template + /* This build() only accepts a function pointer with no arguments. If there is an overloaded function with + zero arguments, the compiler will not be able to auto deduce which function pointer to pick. + In those cases must be expicitly specified (ie, function().build()) to make the compiler to + pick the function pointer taking zero arguments. + */ template inline constexpr const access::Function Builder::build(_returnType(*pFunctor)()) const { return buildFunctor(pFunctor); @@ -42,6 +48,7 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } + /* this build() accepts function pointer with signature that is explicitly specified by 'function<..>()' template params. */ template template inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const @@ -58,11 +65,6 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)() const) const - { - return buildMethodFunctor(pFunctor); - } template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...) const) const @@ -79,7 +81,11 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - template + /* This build() only accepts a const-member-function pointer with no arguments. If there is an overloaded + const-member-function with zero arguments, the compiler will not be able to auto deduce which function pointer to pick. + In those cases must be expicitly specified (ie, methodConst().build()) to make the compiler to + pick the const-member-function pointer taking zero arguments. + */ template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)() const) const { return buildMethodFunctor(pFunctor); From 4a575f89e49072f1ca69e3b6c5ef3397e81c396e Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Thu, 18 Jul 2024 07:38:41 +0530 Subject: [PATCH 2/9] proper indentation --- ReflectionTemplateLib/builder/inc/Builder.h | 8 +- ReflectionTemplateLib/builder/inc/Builder.hpp | 276 +++++++++--------- 2 files changed, 142 insertions(+), 142 deletions(-) diff --git a/ReflectionTemplateLib/builder/inc/Builder.h b/ReflectionTemplateLib/builder/inc/Builder.h index bba74b94..e1e58767 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.h +++ b/ReflectionTemplateLib/builder/inc/Builder.h @@ -85,7 +85,7 @@ namespace rtl { template constexpr const access::Function build(_returnType(_recordType::* pFunctor)() const) const; - }; + }; /* specialized specifically to register overloaded const-member-functions with any arguments. @@ -167,12 +167,12 @@ namespace rtl { template constexpr const access::Function - build(enable_if_same::HEAD > *_= nullptr) const; + build(enable_if_same::HEAD > *_= nullptr) const; template constexpr const access::Function - build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr, - enable_if_not_same::HEAD > *__= nullptr) const; + build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr, + enable_if_not_same::HEAD > *__= nullptr) const; template constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; diff --git a/ReflectionTemplateLib/builder/inc/Builder.hpp b/ReflectionTemplateLib/builder/inc/Builder.hpp index 272f08d4..9983e6fe 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.hpp +++ b/ReflectionTemplateLib/builder/inc/Builder.hpp @@ -11,174 +11,174 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - /* this build() will accept all non-member function pointer, even the ones with zero args (only + /* this build() will accept all non-member and static-member function pointer, even the ones with zero args (only in absence of any other overloaded function) */ template - inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const - { - return buildFunctor(pFunctor); - } - } - + inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const + { + return buildFunctor(pFunctor); + } + } - namespace builder + + namespace builder { - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } /* This build() only accepts a function pointer with no arguments. If there is an overloaded function with zero arguments, the compiler will not be able to auto deduce which function pointer to pick. In those cases must be expicitly specified (ie, function().build()) to make the compiler to pick the function pointer taking zero arguments. - */ template - inline constexpr const access::Function Builder::build(_returnType(*pFunctor)()) const - { - return buildFunctor(pFunctor); - } - } + */ template + inline constexpr const access::Function Builder::build(_returnType(*pFunctor)()) const + { + return buildFunctor(pFunctor); + } + } - namespace builder - { - template - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } + namespace builder + { + template + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } /* this build() accepts function pointer with signature that is explicitly specified by 'function<..>()' template params. */ - template - template - inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const - { - return buildFunctor(pFunctor); - } - } + template + template + inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const + { + return buildFunctor(pFunctor); + } + } - namespace builder - { - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } + namespace builder + { + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } - template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...) const) const - { - return buildMethodFunctor(pFunctor); - } - } + template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...) const) const + { + return buildMethodFunctor(pFunctor); + } + } - namespace builder - { - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } + namespace builder + { + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } /* This build() only accepts a const-member-function pointer with no arguments. If there is an overloaded const-member-function with zero arguments, the compiler will not be able to auto deduce which function pointer to pick. In those cases must be expicitly specified (ie, methodConst().build()) to make the compiler to pick the const-member-function pointer taking zero arguments. - */ template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)() const) const - { - return buildMethodFunctor(pFunctor); - } - } + */ template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)() const) const + { + return buildMethodFunctor(pFunctor); + } + } - namespace builder - { - template - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } - - template - template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...) const) const - { - return buildMethodFunctor(pFunctor); - } - } - - - namespace builder - { - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } - - - template - inline constexpr const access::Function - Builder::build(enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_) const - { - return buildCopyConstructor<_recordType, _signature...>(); - } - - - template - inline constexpr const access::Function - Builder::build(enable_if_same::HEAD > *_) const - { - return buildConstCopyConstructor<_recordType, _signature...>(); - } - - - template - inline constexpr const access::Function - Builder::build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_, - enable_if_not_same::HEAD > *__) const - { - return buildConstructor<_recordType, _signature...>(); - } - - - template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const - { - return buildMethodFunctor(pFunctor); - } - } + namespace builder + { + template + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } + + template + template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...) const) const + { + return buildMethodFunctor(pFunctor); + } + } + + + namespace builder + { + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } + + + template + inline constexpr const access::Function + Builder::build(enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_) const + { + return buildCopyConstructor<_recordType, _signature...>(); + } + + + template + inline constexpr const access::Function + Builder::build(enable_if_same::HEAD > *_) const + { + return buildConstCopyConstructor<_recordType, _signature...>(); + } + + + template + inline constexpr const access::Function + Builder::build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_, + enable_if_not_same::HEAD > *__) const + { + return buildConstructor<_recordType, _signature...>(); + } + + + template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const + { + return buildMethodFunctor(pFunctor); + } + } - namespace builder - { - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } + namespace builder + { + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } - template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)()) const - { - return buildMethodFunctor(pFunctor); - } - } + template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)()) const + { + return buildMethodFunctor(pFunctor); + } + } - namespace builder - { - template - inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : ReflectionBuilder(pNamespace, pRecord, pFunction) { - } + namespace builder + { + template + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } - template - template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const - { - return buildMethodFunctor(pFunctor); - } - } + template + template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const + { + return buildMethodFunctor(pFunctor); + } + } } \ No newline at end of file From 3fcedea00cc60c73d23f08fc26c64966d8ea58a2 Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Thu, 18 Jul 2024 15:47:01 +0530 Subject: [PATCH 3/9] formatted comments. --- CxxTypeRegistration/src/MyReflection.cpp | 4 +- ReflectionTemplateLib/builder/inc/Builder.h | 105 ++++++++++-------- ReflectionTemplateLib/builder/inc/Builder.hpp | 93 ++++++++++++---- 3 files changed, 133 insertions(+), 69 deletions(-) diff --git a/CxxTypeRegistration/src/MyReflection.cpp b/CxxTypeRegistration/src/MyReflection.cpp index adcb6d02..f03f2f1e 100644 --- a/CxxTypeRegistration/src/MyReflection.cpp +++ b/CxxTypeRegistration/src/MyReflection.cpp @@ -34,7 +34,9 @@ CxxMirror& MyReflection::instance() Reflect().function(str_reverseString).build(reverseString), //overloaded function, takes 'const char*' arguments. Reflect().function(str_getComplexNumAsString).build(getComplexNumAsString), //unique function, no overloads, no need to specify signature as template parameters. - //Grouping functions under a namespace, which is optional. they can be registered without it as well. + /*Grouping functions under a namespace, which is optional.they can be registered without it as well. + but if registered under namspace, then to retrieve it from CxxMirror object, namespace name must be passed, + ex - cxxMirror.getFunction("namespace_name", "function_name") & cxxMirror.getRecord("namespace_name", "record_name")*/ Reflect().nameSpace(str_complex).function(str_setReal).build(complex::setReal), Reflect().nameSpace(str_complex).function(str_setImaginary).build(complex::setImaginary), Reflect().nameSpace(str_complex).function(str_getMagnitude).build(complex::getMagnitude), diff --git a/ReflectionTemplateLib/builder/inc/Builder.h b/ReflectionTemplateLib/builder/inc/Builder.h index e1e58767..488e240c 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.h +++ b/ReflectionTemplateLib/builder/inc/Builder.h @@ -7,14 +7,16 @@ namespace rtl { namespace builder { - /* Provides interface to register all sort of functions, methods & constructors. - _signature: arguments types of the functions/constructors. - _typeQ: Builder, specialized with TypeQ, - TypeQ::None - provides interface to register non-member and static member funtions. - TypeQ::Mute - provides interface to register member funtion. - TypeQ::Const - provides interface to register const-member funtions. - Every builder specialization has a 'build()' function, which takes function pointer as - an argument which can be member(static/const)/non-member. + /* @struct: Builder + @param: specialized with TypeQ, + * TypeQ::Mute - provides interface to register member funtion. + * TypeQ::Const - provides interface to register const-member funtions. + * TypeQ::None - provides interface to register non-member and static member funtions. + @param: + * _signature: arguments types of functions pointers or constructors (auto deduced/explicitly specified). + * provides interface to register all sort of functions, methods & constructors. + * every specialization has a 'build()' function, which accepts a function pointer. + * function pointer can be non-member or member(static/const/non-const) functions. */ template struct Builder; } @@ -22,11 +24,12 @@ namespace rtl { namespace builder { - /* specialized specifically to register overloaded non-member & static member functions with no arguments. - Objects of this class will be created & returned by these functions, - - Reflect::function(..) - - RecordBuilder<_recordType>::methodStatic(..) - with template parameter is only 'void', explicitly specified. + /* @struct: Builder + * specialized specifically to register overloaded non-member & static member functions with no arguments. + * Objects of this class will be created & returned by these functions, + * - Reflect::function(..) + * - RecordBuilder<_recordType>::methodStatic(..) + * with template parameter is only 'void', explicitly specified. */ template<> struct Builder : protected detail::ReflectionBuilder { @@ -38,11 +41,12 @@ namespace rtl { }; - /* specialized specifically to register overloaded non-member & static member functions with any arguments. - Objects of this class will be created & returned by these functions, - - Reflect::function<...>(..) - - RecordBuilder<_recordType>::methodStatic<...>(..) - with template parameters can be anything, explicitly specified. + /* @struct: Builder + * specialized specifically to register overloaded non-member & static member functions with any arguments. + * Objects of this class will be created & returned by these functions, + * - Reflect::function<...>(..) + * - RecordBuilder<_recordType>::methodStatic<...>(..) + * with template parameters can be anything, explicitly specified. */ template struct Builder : protected detail::ReflectionBuilder { @@ -54,11 +58,12 @@ namespace rtl { }; - /* specialized specifically to register non-member functions with any signature and with no overloads. - Objects of this class will be created & returned by these functions, - - Reflect::function(..) - - RecordBuilder<_recordType>::methodStatic(..) - with no template parameters specified. + /* @struct: Builder + * specialized specifically to register non-member functions with any signature and with no overloads. + * Objects of this class will be created & returned by these functions, + * - Reflect::function(..) + * - RecordBuilder<_recordType>::methodStatic(..) + * with no template parameters specified. */ template<> struct Builder : protected detail::ReflectionBuilder { @@ -73,10 +78,11 @@ namespace rtl { namespace builder { - /* specialized specifically to register overloaded const-member-functions with no arguments. - Objects of this class will be created & returned by function, - - RecordBuilder<_recordType>::methodConst(..) - with template parameters is only 'void' explicitly specified. + /* @struct: Builder + * specialized specifically to register overloaded const-member-functions with no arguments. + * Objects of this class will be created & returned by function, + * - RecordBuilder<_recordType>::methodConst(..) + * with template parameters is only 'void' explicitly specified. */ template<> struct Builder : protected detail::ReflectionBuilder { @@ -88,10 +94,11 @@ namespace rtl { }; - /* specialized specifically to register overloaded const-member-functions with any arguments. - Objects of this class will be created & returned by function, - - RecordBuilder<_recordType>::methodConst<...>(..) - with template parameters can be anything, explicitly specified. + /* @struct: Builder + * specialized specifically to register overloaded const-member-functions with any arguments. + * Objects of this class will be created & returned by function, + * - RecordBuilder<_recordType>::methodConst<...>(..) + * with template parameters can be anything, explicitly specified. */ template struct Builder : protected detail::ReflectionBuilder { @@ -103,10 +110,11 @@ namespace rtl { }; - /* specialized specifically to register non-overloaded const-member-functions with any arguments. - Objects of this class will be created & returned by function, - - RecordBuilder<_recordType>::methodConst() - with no template parameters specified. + /* @struct: Builder + * specialized specifically to register non-overloaded const-member-functions with any arguments. + * Objects of this class will be created & returned by function, + * - RecordBuilder<_recordType>::methodConst() + * with no template parameters specified. */ template<> struct Builder : protected detail::ReflectionBuilder { @@ -121,10 +129,11 @@ namespace rtl { namespace builder { - /* specialized specifically to register overloaded non-const-member-functions with no arguments. - Objects of this class will be created & returned by function, - - RecordBuilder<_recordType>::method(..) - with template parameters is only 'void' explicitly specified. + /* @struct: Builder + * specialized specifically to register overloaded non-const-member-functions with no arguments. + * Objects of this class will be created & returned by function, + * - RecordBuilder<_recordType>::method(..) + * with template parameters is only 'void' explicitly specified. */ template<> struct Builder : protected detail::ReflectionBuilder { @@ -136,10 +145,11 @@ namespace rtl { }; - /* specialized specifically to register overloaded non-const-member-functions with no arguments. - Objects of this class will be created & returned by function, - - RecordBuilder<_recordType>::method(..) - with template parameters is only 'void' explicitly specified. + /* @struct: Builder + * specialized specifically to register overloaded non-const-member-functions with no arguments. + * Objects of this class will be created & returned by function, + * - RecordBuilder<_recordType>::method(..) + * with template parameters is only 'void' explicitly specified. */ template struct Builder : protected detail::ReflectionBuilder { @@ -151,10 +161,11 @@ namespace rtl { }; - /* specialized specifically to register non-overloaded non-const-member-functions and constructors with any arguments. - Objects of this class will be created & returned by function, - - RecordBuilder<_recordType>::method() - with no template parameters specified. - - RecordBuilder<_recordType>::constructor<...>() - template parameters can be anything, explicitly specified. + /* @struct: Builder + * specialized specifically to register non-overloaded non-const-member-functions and constructors with any arguments. + * Objects of this class will be created & returned by function, + * - RecordBuilder<_recordType>::method() - with no template parameters specified. + * - RecordBuilder<_recordType>::constructor<...>() - template parameters can be anything or none, explicitly specified. */ template<> struct Builder : protected detail::ReflectionBuilder { diff --git a/ReflectionTemplateLib/builder/inc/Builder.hpp b/ReflectionTemplateLib/builder/inc/Builder.hpp index 9983e6fe..d0e63a1c 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.hpp +++ b/ReflectionTemplateLib/builder/inc/Builder.hpp @@ -11,8 +11,11 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - /* this build() will accept all non-member and static-member function pointer, even the ones with zero args (only - in absence of any other overloaded function) + /* @method: build() + @param: _returnType(*)(_signature...) + * accepts all non-member and static-member function pointer. + * called on the objects returned by 'Reflect::function()' & 'RecordBuilder<_recordType>::methodStatic(..)'. + * template params are auto deduced from the function pointer passed. */ template inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const { @@ -28,10 +31,11 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - /* This build() only accepts a function pointer with no arguments. If there is an overloaded function with - zero arguments, the compiler will not be able to auto deduce which function pointer to pick. - In those cases must be expicitly specified (ie, function().build()) to make the compiler to - pick the function pointer taking zero arguments. + /* @method: build() + @param: _returnType(*)() + * accepts a non-member or static-member function pointer with no arguments. + * called on objects returned by 'Reflect::function(..)' & 'RecordBuilder<_recordType>::methodStatic(..)' + * template param 'void' is explicitly specified. */ template inline constexpr const access::Function Builder::build(_returnType(*pFunctor)()) const { @@ -48,8 +52,13 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - /* this build() accepts function pointer with signature that is explicitly specified by 'function<..>()' template params. */ - template + + /* @method: build() + @param: _returnType(*)(_signature...) + * it accepts a non-member or static-member function pointer. + * called on objects returned by 'Reflect::function<...>(..)' & 'RecordBuilder<_recordType>::methodStatic<...>(..)'. + * template params are explicitly specified. + */ template template inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const { @@ -65,8 +74,12 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - - template + /* @method: build() + @param: _returnType(_recordType::*)(_signature...) const. + * accepts function pointer of a const-member-function with any signature. + * called on object returned by 'RecordBuilder<_recordType>::methodConst()' + * template params will be auto deduced from the function pointer passed. + */ template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...) const) const { return buildMethodFunctor(pFunctor); @@ -81,10 +94,11 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - /* This build() only accepts a const-member-function pointer with no arguments. If there is an overloaded - const-member-function with zero arguments, the compiler will not be able to auto deduce which function pointer to pick. - In those cases must be expicitly specified (ie, methodConst().build()) to make the compiler to - pick the const-member-function pointer taking zero arguments. + /* @method: build() + @param: _returnType(_recordType::*)() const. + * accepts a const-member-function pointer with no arguments. + * called on object returned by 'RecordBuilder<_recordType>::methodConst()' + * template param 'void' is explicitly specified. */ template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)() const) const { @@ -101,7 +115,12 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - template + /* @method: build() + @param: _returnType(_recordType::*)(_signature...) const. + * accepts a const-member-function pointer with any arguments. + * called on object returned by 'RecordBuilder<_recordType>::methodConst<...>()' + * template param are explicitly specified. + */ template template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...) const) const { @@ -118,7 +137,12 @@ namespace rtl { } - template + /* @method: build() + @param: '_' defaulted to nullptr to enable SFINAE. (params have no significance after compilation) + * builds copy constructor which takes non-const object source ref, accepts no arguments. + * called on object returned by 'RecordBuilder<_recordType>::constructor<_recordType&>()' + * template params <_recordType&>, explicitly specified. + */ template inline constexpr const access::Function Builder::build(enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_) const { @@ -126,7 +150,12 @@ namespace rtl { } - template + /* @method: build() + @param: '_' defaulted to nullptr to enable SFINAE. (params have no significance after compilation) + * builds copy constructor which takes const object source ref, accepts no arguments. + * called on object returned by 'RecordBuilder<_recordType>::constructor()' + * template params , explicitly specified. + */ template inline constexpr const access::Function Builder::build(enable_if_same::HEAD > *_) const { @@ -134,7 +163,13 @@ namespace rtl { } - template + /* @method: build() + @param: '_' & '__' defaulted to nullptr to enable SFINAE. (params have no significance after compilation) + * builds copy constructor which takes const object source, accepts no arguments. + * called on object returned by 'RecordBuilder<_recordType>::constructor<...>()' + * template params <...>, explicitly specified. + * calling with zero template params will build the default constructor ie, 'RecordBuilder<_recordType>::constructor()' + */ template inline constexpr const access::Function Builder::build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_, enable_if_not_same::HEAD > *__) const @@ -143,7 +178,12 @@ namespace rtl { } - template + /* @method: build() + @param: _returnType(_recordType::*)(_signature...) + * accepts a non-const-member-function pointer with any arguments. + * called on object returned by 'RecordBuilder<_recordType>::method()' + * template params are auto deduced from the pointer passed. + */ template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const { return buildMethodFunctor(pFunctor); @@ -158,7 +198,13 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - template + + /* @method: build() + @param: _returnType(_recordType::*)() + * accepts a non-const-member-function pointer with no arguments. + * called on object returned by 'RecordBuilder<_recordType>::method()' + * template param 'void' is explicitly specified. + */ template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)()) const { return buildMethodFunctor(pFunctor); @@ -174,7 +220,12 @@ namespace rtl { : ReflectionBuilder(pNamespace, pRecord, pFunction) { } - template + /* @method: build() + @param: _returnType(_recordType::*)(_signature...) + * accepts a non-const-member-function pointer with any arguments. + * called on object returned by 'RecordBuilder<_recordType>::method<...>()' + * template params are explicitly specified. + */ template template inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const { From d23493c92f69afecf370d61529a045f7c9207916 Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Thu, 18 Jul 2024 20:29:48 +0530 Subject: [PATCH 4/9] proper indentation --- ReflectionTemplateLib/builder/inc/Builder.h | 12 +- ReflectionTemplateLib/builder/inc/Builder.hpp | 46 ++---- .../builder/inc/ConstructorBuilder.h | 55 ++------ .../builder/inc/ConstructorBuilder.hpp | 100 +++++-------- .../builder/inc/RecordBuilder.h | 48 +++---- .../builder/inc/RecordBuilder.hpp | 133 ++++++++++-------- 6 files changed, 161 insertions(+), 233 deletions(-) diff --git a/ReflectionTemplateLib/builder/inc/Builder.h b/ReflectionTemplateLib/builder/inc/Builder.h index 488e240c..496949c2 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.h +++ b/ReflectionTemplateLib/builder/inc/Builder.h @@ -173,17 +173,7 @@ namespace rtl { const std::string& pFunction); template - constexpr const access::Function - build(enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr) const; - - template - constexpr const access::Function - build(enable_if_same::HEAD > *_= nullptr) const; - - template - constexpr const access::Function - build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr, - enable_if_not_same::HEAD > *__= nullptr) const; + constexpr const access::Function build() const; template constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; diff --git a/ReflectionTemplateLib/builder/inc/Builder.hpp b/ReflectionTemplateLib/builder/inc/Builder.hpp index d0e63a1c..a625a71e 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.hpp +++ b/ReflectionTemplateLib/builder/inc/Builder.hpp @@ -138,43 +138,27 @@ namespace rtl { /* @method: build() - @param: '_' defaulted to nullptr to enable SFINAE. (params have no significance after compilation) - * builds copy constructor which takes non-const object source ref, accepts no arguments. - * called on object returned by 'RecordBuilder<_recordType>::constructor<_recordType&>()' - * template params <_recordType&>, explicitly specified. - */ template - inline constexpr const access::Function - Builder::build(enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_) const - { - return buildCopyConstructor<_recordType, _signature...>(); - } - - - /* @method: build() - @param: '_' defaulted to nullptr to enable SFINAE. (params have no significance after compilation) - * builds copy constructor which takes const object source ref, accepts no arguments. - * called on object returned by 'RecordBuilder<_recordType>::constructor()' - * template params , explicitly specified. - */ template - inline constexpr const access::Function - Builder::build(enable_if_same::HEAD > *_) const - { - return buildConstCopyConstructor<_recordType, _signature...>(); - } - - - /* @method: build() - @param: '_' & '__' defaulted to nullptr to enable SFINAE. (params have no significance after compilation) - * builds copy constructor which takes const object source, accepts no arguments. + @param: none + * accepts no arguments, builds copy constructor which takes const object source. * called on object returned by 'RecordBuilder<_recordType>::constructor<...>()' * template params <...>, explicitly specified. * calling with zero template params will build the default constructor ie, 'RecordBuilder<_recordType>::constructor()' */ template inline constexpr const access::Function - Builder::build(enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_, - enable_if_not_same::HEAD > *__) const + Builder::build() const { - return buildConstructor<_recordType, _signature...>(); + if constexpr (std::is_same_v<_recordType&, typename detail::TypeId<_signature...>::HEAD>) + { + return buildCopyConstructor<_recordType, _signature...>(); + } + else if constexpr (std::is_same_v::HEAD>) + { + return buildConstCopyConstructor<_recordType, _signature...>(); + } + else + { + return buildConstructor<_recordType, _signature...>(); + } } diff --git a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h index 8cb70b16..1e973aed 100644 --- a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h +++ b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h @@ -3,52 +3,23 @@ #include "Constants.h" namespace rtl { + namespace builder + { + template + class ConstructorBuilder + { + const std::string& m_record; + const std::string& m_namespace; + const FunctorType m_ctorType; - namespace builder - { - template - class ConstructorBuilder - { - const std::string& m_record; - const std::string& m_namespace; - const FunctorType m_ctorType; + ConstructorBuilder() = delete; - ConstructorBuilder() = delete; + public: - public: + ConstructorBuilder(const std::string& pNamespace, const std::string& pRecord, + const FunctorType& pCtorType); - ConstructorBuilder(const std::string& pNamespace, const std::string& pRecord, - const FunctorType& pCtorType); - - inline constexpr const access::Function build() const; - }; - } - - - namespace builder - { - template<> - class ConstructorBuilder<> - { - public: - - template - static constexpr const ConstructorBuilder<_recordType, _signature...> - select(const std::string& pNamespace, const std::string& pRecord, - enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr); - - - template - static constexpr const ConstructorBuilder<_recordType, _signature...> - select(const std::string& pNamespace, const std::string& pRecord, - enable_if_same::HEAD > *_= nullptr); - - - template - static constexpr const ConstructorBuilder<_recordType, _signature...> - select(const std::string& pNamespace, const std::string& pRecord, - enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_= nullptr, - enable_if_not_same::HEAD > *__= nullptr); + inline constexpr const access::Function build() const; }; } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp index 5f8047b9..a5c781de 100644 --- a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp +++ b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp @@ -6,68 +6,40 @@ namespace rtl { - namespace builder - { - template - inline ConstructorBuilder<_recordType, _ctorSignature...>::ConstructorBuilder(const std::string& pNamespace, const std::string& pRecord, - const FunctorType& pCtorType) - : m_record(pRecord) - , m_namespace(pNamespace) - , m_ctorType(pCtorType) - { - } - - - template - inline constexpr const access::Function ConstructorBuilder<_recordType, _ctorSignature...>::build() const - { - switch (m_ctorType) - { - default: - case FunctorType::Ctor: { - const auto& ctorName = CtorName::ctor(m_record); - return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); - } - case FunctorType::CopyCtor: { - const auto& ctorName = CtorName::copy(m_record); - return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); - } - case FunctorType::CopyCtorConst: { - const auto& ctorName = CtorName::constCopy(m_record); - return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); - } - } - } - } - - - namespace builder - { - template - inline constexpr const ConstructorBuilder<_recordType, _signature...> - ConstructorBuilder<>::select(const std::string& pNamespace, const std::string& pRecord, - enable_if_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_) - { - return ConstructorBuilder<_recordType, _signature...>(pNamespace, pRecord, FunctorType::CopyCtor); - } - - - template - inline constexpr const ConstructorBuilder<_recordType, _signature...> - ConstructorBuilder<>::select(const std::string& pNamespace, const std::string& pRecord, - enable_if_same::HEAD > *_) - { - return ConstructorBuilder<_recordType, _signature...>(pNamespace, pRecord, FunctorType::CopyCtorConst); - } - - - template - inline constexpr const ConstructorBuilder<_recordType, _signature...> - ConstructorBuilder<>::select(const std::string& pNamespace, const std::string& pRecord, - enable_if_not_same<_recordType&, typename detail::TypeId<_signature...>::HEAD > *_, - enable_if_not_same::HEAD > *__) - { - return ConstructorBuilder<_recordType, _signature...>(pNamespace, pRecord, FunctorType::Ctor); - } - } + namespace builder + { + template + inline ConstructorBuilder<_recordType, _ctorSignature...>::ConstructorBuilder(const std::string& pNamespace, const std::string& pRecord, + const FunctorType& pCtorType) + : m_record(pRecord) + , m_namespace(pNamespace) + , m_ctorType(pCtorType) + { + } + + + template + inline constexpr const access::Function ConstructorBuilder<_recordType, _ctorSignature...>::build() const + { + switch (m_ctorType) + { + default: + case FunctorType::Ctor: + { + const auto& ctorName = CtorName::ctor(m_record); + return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); + } + case FunctorType::CopyCtor: + { + const auto& ctorName = CtorName::copy(m_record); + return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); + } + case FunctorType::CopyCtorConst: + { + const auto& ctorName = CtorName::constCopy(m_record); + return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); + } + } + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/RecordBuilder.h b/ReflectionTemplateLib/builder/inc/RecordBuilder.h index dcc1d14e..a459d1ee 100644 --- a/ReflectionTemplateLib/builder/inc/RecordBuilder.h +++ b/ReflectionTemplateLib/builder/inc/RecordBuilder.h @@ -4,38 +4,38 @@ namespace rtl { - namespace builder - { - template - class ConstructorBuilder; + namespace builder + { + template + class ConstructorBuilder; - template - class RecordBuilder - { - const std::string& m_record; - const std::string& m_namespace; + template + class RecordBuilder + { + const std::string& m_record; + const std::string& m_namespace; - public: + public: - RecordBuilder(const std::string& pNamespace, const std::string& pRecord); + RecordBuilder(const std::string& pNamespace, const std::string& pRecord); - template - constexpr const ConstructorBuilder<_recordType, _signature...> constructor() const; + template + constexpr const ConstructorBuilder<_recordType, _signature...> constructor() const; - constexpr const Builder method(const std::string& pFunction) const; + constexpr const Builder method(const std::string& pFunction) const; - constexpr const Builder methodStatic(const std::string& pFunction) const; + constexpr const Builder methodStatic(const std::string& pFunction) const; - constexpr const Builder methodConst(const std::string& pFunction) const; + constexpr const Builder methodConst(const std::string& pFunction) const; - template - constexpr const Builder method(const std::string& pFunction) const; + template + constexpr const Builder method(const std::string& pFunction) const; - template - constexpr const Builder methodStatic(const std::string& pFunction) const; + template + constexpr const Builder methodStatic(const std::string& pFunction) const; - template - constexpr const Builder methodConst(const std::string& pFunction) const; - }; - } + template + constexpr const Builder methodConst(const std::string& pFunction) const; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp b/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp index a119ad1e..05120816 100644 --- a/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp +++ b/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp @@ -5,65 +5,76 @@ namespace rtl { - namespace builder - { - template - inline RecordBuilder<_recordType>::RecordBuilder(const std::string& pNamespace, const std::string& pRecord) - : m_record(pRecord) - , m_namespace(pNamespace) { - } - - - template - template - inline constexpr const ConstructorBuilder<_recordType, _signature...> RecordBuilder<_recordType>::constructor() const - { - return ConstructorBuilder<>::select<_recordType, _signature...>(m_namespace, m_record); - } - - - template - inline constexpr const Builder RecordBuilder<_recordType>::methodStatic(const std::string& pFunction) const - { - return Builder(m_namespace, m_record, pFunction); - } - - - template - template - inline constexpr const Builder RecordBuilder<_recordType>::methodStatic(const std::string& pFunction) const - { - return Builder(m_namespace, m_record, pFunction); - } - - - template - inline constexpr const Builder RecordBuilder<_recordType>::method(const std::string& pFunction) const - { - return Builder(m_namespace, m_record, pFunction); - } - - - template - inline constexpr const Builder RecordBuilder<_recordType>::methodConst(const std::string& pFunction) const - { - return Builder(m_namespace, m_record, pFunction); - } - - - template - template - inline constexpr const Builder RecordBuilder<_recordType>::method(const std::string& pFunction) const - { - return Builder(m_namespace, m_record, pFunction); - } - - - template - template - inline constexpr const Builder RecordBuilder<_recordType>::methodConst(const std::string& pFunction) const - { - return Builder(m_namespace, m_record, pFunction); - } - } + namespace builder + { + template + inline RecordBuilder<_recordType>::RecordBuilder(const std::string& pNamespace, const std::string& pRecord) + : m_record(pRecord) + , m_namespace(pNamespace) { + } + + + template + template + inline constexpr const ConstructorBuilder<_recordType, _signature...> RecordBuilder<_recordType>::constructor() const + { + if constexpr (std::is_same_v<_recordType&, typename detail::TypeId<_signature...>::HEAD>) + { + return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::CopyCtor); + } + else if constexpr (std::is_same_v::HEAD>) + { + return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::CopyCtorConst); + } + else + { + return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::Ctor); + } + } + + + template + inline constexpr const Builder RecordBuilder<_recordType>::methodStatic(const std::string& pFunction) const + { + return Builder(m_namespace, m_record, pFunction); + } + + + template + template + inline constexpr const Builder RecordBuilder<_recordType>::methodStatic(const std::string& pFunction) const + { + return Builder(m_namespace, m_record, pFunction); + } + + + template + inline constexpr const Builder RecordBuilder<_recordType>::method(const std::string& pFunction) const + { + return Builder(m_namespace, m_record, pFunction); + } + + + template + inline constexpr const Builder RecordBuilder<_recordType>::methodConst(const std::string& pFunction) const + { + return Builder(m_namespace, m_record, pFunction); + } + + + template + template + inline constexpr const Builder RecordBuilder<_recordType>::method(const std::string& pFunction) const + { + return Builder(m_namespace, m_record, pFunction); + } + + + template + template + inline constexpr const Builder RecordBuilder<_recordType>::methodConst(const std::string& pFunction) const + { + return Builder(m_namespace, m_record, pFunction); + } + } } \ No newline at end of file From dbc57f5d178e1fa1c1e465acf9aea613f39914b1 Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Fri, 19 Jul 2024 13:03:54 +0530 Subject: [PATCH 5/9] builders Comments done. --- ReflectionTemplateLib/builder/inc/Builder.hpp | 13 +++ .../builder/inc/ConstructorBuilder.h | 21 +++- .../builder/inc/ConstructorBuilder.hpp | 30 ++--- .../builder/inc/RecordBuilder.h | 5 +- .../builder/inc/RecordBuilder.hpp | 109 +++++++++++++----- ReflectionTemplateLib/builder/inc/Reflect.h | 44 +++---- ReflectionTemplateLib/builder/inc/Reflect.hpp | 83 ++++++++----- ReflectionTemplateLib/common/Constants.h | 8 +- 8 files changed, 211 insertions(+), 102 deletions(-) diff --git a/ReflectionTemplateLib/builder/inc/Builder.hpp b/ReflectionTemplateLib/builder/inc/Builder.hpp index ba3e9dad..054db68e 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.hpp +++ b/ReflectionTemplateLib/builder/inc/Builder.hpp @@ -13,6 +13,7 @@ namespace rtl { /* @method: build() @param: _returnType(*)(_signature...) + @return: 'access::Function' object. * accepts all non-member and static-member function pointer. * called on the objects returned by 'Reflect::function()' & 'RecordBuilder<_recordType>::methodStatic(..)'. * template params are auto deduced from the function pointer passed. @@ -33,6 +34,7 @@ namespace rtl { /* @method: build() @param: _returnType(*)() + @return: 'access::Function' object. * accepts a non-member or static-member function pointer with no arguments. * called on objects returned by 'Reflect::function(..)' & 'RecordBuilder<_recordType>::methodStatic(..)' * template param 'void' is explicitly specified. @@ -55,6 +57,7 @@ namespace rtl { /* @method: build() @param: _returnType(*)(_signature...) + @return: 'access::Function' object. * it accepts a non-member or static-member function pointer. * called on objects returned by 'Reflect::function<...>(..)' & 'RecordBuilder<_recordType>::methodStatic<...>(..)'. * template params are explicitly specified. @@ -76,6 +79,7 @@ namespace rtl { /* @method: build() @param: _returnType(_recordType::*)(_signature...) const. + @return: 'access::Function' object. * accepts function pointer of a const-member-function with any signature. * called on object returned by 'RecordBuilder<_recordType>::methodConst()' * template params will be auto deduced from the function pointer passed. @@ -96,6 +100,7 @@ namespace rtl { /* @method: build() @param: _returnType(_recordType::*)() const. + @return: 'access::Function' object. * accepts a const-member-function pointer with no arguments. * called on object returned by 'RecordBuilder<_recordType>::methodConst()' * template param 'void' is explicitly specified. @@ -117,6 +122,7 @@ namespace rtl { /* @method: build() @param: _returnType(_recordType::*)(_signature...) const. + @return: 'access::Function' object. * accepts a const-member-function pointer with any arguments. * called on object returned by 'RecordBuilder<_recordType>::methodConst<...>()' * template param are explicitly specified. @@ -139,6 +145,7 @@ namespace rtl { /* @method: build() @param: none + @return: 'access::Function' object. * accepts no arguments, builds copy constructor which takes const object source. * called on object returned by 'RecordBuilder<_recordType>::constructor<...>()' * template params <...>, explicitly specified. @@ -147,14 +154,17 @@ namespace rtl { inline constexpr const access::Function Builder::build() const { + //this code-block is retained by compiler, if copy constructor with non-const ref('_recordType&') is being registered. if constexpr (std::is_same_v<_recordType&, typename detail::TypeId<_signature...>::HEAD>) { return buildCopyConstructor<_recordType, _signature...>(); } + //this code-block is retained by compiler, if copy constructor with const-ref('const _recordType&') is being registered. else if constexpr (std::is_same_v::HEAD>) { return buildConstCopyConstructor<_recordType, _signature...>(); } + //if any other constructor except, copy constructor is being registered, this code-block will be retained. else { return buildConstructor<_recordType, _signature...>(); @@ -164,6 +174,7 @@ namespace rtl { /* @method: build() @param: _returnType(_recordType::*)(_signature...) + @return: 'access::Function' object. * accepts a non-const-member-function pointer with any arguments. * called on object returned by 'RecordBuilder<_recordType>::method()' * template params are auto deduced from the pointer passed. @@ -185,6 +196,7 @@ namespace rtl { /* @method: build() @param: _returnType(_recordType::*)() + @return: 'access::Function' object. * accepts a non-const-member-function pointer with no arguments. * called on object returned by 'RecordBuilder<_recordType>::method()' * template param 'void' is explicitly specified. @@ -206,6 +218,7 @@ namespace rtl { /* @method: build() @param: _returnType(_recordType::*)(_signature...) + @return: 'access::Function' object. * accepts a non-const-member-function pointer with any arguments. * called on object returned by 'RecordBuilder<_recordType>::method<...>()' * template params are explicitly specified. diff --git a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h index 91830b80..c29db0ee 100644 --- a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h +++ b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h @@ -3,14 +3,31 @@ #include "Constants.h" namespace rtl { + namespace builder { - template + /* @class: ConstructorBuilder + @param: _recordType - struct/class type. + * _signature...- constructor args type (none/_record&/const _record& or any combination of parameters) + * provides interface to register constructors/destructor of a class/struct. + * when the very first constructor(any- copy/default/parametrized) is registered, destructor gets registered implicitly. + * all the objects are created via reflection are on heap, using 'new'. + * the constructed objects are returned wrapped in 'Instance' object, with type erased. + * lifetime of created objects are managed using 'shared_ptr'. + */ template class ConstructorBuilder { + //given name of the class/struct. const std::string& m_record; + + //given name of the namespace. const std::string& m_namespace; - const FunctorType m_ctorType; + + /* type of constructor to be registered. + FunctorType::Ctor - default/parametrized constructor. + FunctorType::CopyCtor - copy constructor args, '_recordType&' + FunctorType::CopyCtorConst - copy constructor args, 'const _recordType&' + */ const FunctorType m_ctorType; ConstructorBuilder() = delete; diff --git a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp index a5c781de..e6608590 100644 --- a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp +++ b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp @@ -18,28 +18,18 @@ namespace rtl { } - template + /* @method: build() + @param: none + @return: 'Function' object. + * constructs temparory object of class Builder with given class/struct, namespace name & constructor type. + * forwards the call to Builder::build(). + */ template inline constexpr const access::Function ConstructorBuilder<_recordType, _ctorSignature...>::build() const { - switch (m_ctorType) - { - default: - case FunctorType::Ctor: - { - const auto& ctorName = CtorName::ctor(m_record); - return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); - } - case FunctorType::CopyCtor: - { - const auto& ctorName = CtorName::copy(m_record); - return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); - } - case FunctorType::CopyCtorConst: - { - const auto& ctorName = CtorName::constCopy(m_record); - return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); - } - } + const auto& ctorName = (m_ctorType == FunctorType::CopyCtor ? CtorName::copy(m_record) : + (m_ctorType == FunctorType::CopyCtorConst ? CtorName::constCopy(m_record) : CtorName::ctor(m_record))); + + return Builder(m_namespace, m_record, ctorName).build<_recordType, _ctorSignature...>(); } } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/RecordBuilder.h b/ReflectionTemplateLib/builder/inc/RecordBuilder.h index a459d1ee..21970f2c 100644 --- a/ReflectionTemplateLib/builder/inc/RecordBuilder.h +++ b/ReflectionTemplateLib/builder/inc/RecordBuilder.h @@ -9,7 +9,10 @@ namespace rtl { template class ConstructorBuilder; - template + /* @class: RecordBuilder + @param: <_recordType>, a struct/class type. + * provides interface to register member-function & constructors/destructor of a class/struct. + */ template class RecordBuilder { const std::string& m_record; diff --git a/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp b/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp index 1e088c7a..5de80103 100644 --- a/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp +++ b/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp @@ -14,67 +14,120 @@ namespace rtl { } - template - template - inline constexpr const ConstructorBuilder<_recordType, _signature...> RecordBuilder<_recordType>::constructor() const - { - if constexpr (std::is_same_v<_recordType&, typename detail::TypeId<_signature...>::HEAD>) - { - return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::CopyCtor); - } - else if constexpr (std::is_same_v::HEAD>) - { - return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::CopyCtorConst); - } - else - { - return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::Ctor); - } - } - - - template + /* @method: methodStatic() + @param: std::string, name of function as string. + @return: Builder + * registers only static member functions. + * used for registering unique static member function, if overload exists, use templated version 'methodStatic<...>()'. + * the 'build(..)' called on return object will accepts static member function pointer only. + * compiler error on 'build(..)' if non-static member or non-member function pointer is passed. + */ template inline constexpr const Builder RecordBuilder<_recordType>::methodStatic(const std::string& pFunction) const { return Builder(m_namespace, m_record, pFunction); } - template + /* @method: methodStatic<...>() + @param: std::string, name of function as string. + @return: Builder + * registers only static member functions. + * used for registering overloads, if unique member function, use non-templated version 'methodStatic()'. + * template parameters must be explicitly specified, should be exactly same as the member-function being registered. + * the 'build(..)' called on return object will accepts static member function pointer only. + * compiler error on 'build(..)' if const member or non-member function pointer is passed. + */ template template - inline constexpr const Builder RecordBuilder<_recordType>::methodStatic(const std::string& pFunction) const + inline constexpr const Builder RecordBuilder<_recordType>::methodStatic(const std::string& pFunction) const { return Builder(m_namespace, m_record, pFunction); } - template + /* @method: method() + @param: std::string, name of function as string. + @return: Builder + * registers non-const, non-static member functions. + * the 'build(..)' called on return object will accepts non-const, non-static member-function-pointer only. + * compiler error on 'build(..)' if const, static member or non-member function pointer is passed. + */ template inline constexpr const Builder RecordBuilder<_recordType>::method(const std::string& pFunction) const { return Builder(m_namespace, m_record, pFunction); } - template + /* @method: methodConst() + @param: std::string, name of function as string. + @return: Builder + * registers const member functions. + * used for registering unique member function, if overload exists, use templated version 'methodConst<...>()'. + * template parameters must be explicitly specified, should be exactly same as the member-function being registered. + * the 'build(..)' called on return object will accepts non-const member-function-pointer only. + * compiler error 'build(..)' if non-const, static member or non-member function pointer is passed. + */ template inline constexpr const Builder RecordBuilder<_recordType>::methodConst(const std::string& pFunction) const { return Builder(m_namespace, m_record, pFunction); } - template + /* @method: method() + @param: std::string, name of function as string. + @return: Builder + * registers non-const member functions. + * used for registering overloads, for unique member function, use non-templated version 'method()'. + * template parameters must be explicitly specified, should be exactly same as the member-function being registered. + * the 'build(..)' called on return object will accepts non-const member-function-pointer only. + * compiler error on 'build(..)' if const, static member or non-member function pointer is passed. + */ template template - inline constexpr const Builder RecordBuilder<_recordType>::method(const std::string& pFunction) const + inline constexpr const Builder RecordBuilder<_recordType>::method(const std::string& pFunction) const { return Builder(m_namespace, m_record, pFunction); } - template + /* @method: methodConst<...>() + @param: std::string, name of function as string. + @return: Builder + * registers const member functions. + * used for registering overloads, for unique member function, use non-templated version 'methodConst()'. + * template parameters must be explicitly specified, should be exactly same as the member-function being registered. + * the 'build(..)' called on return object will accepts const member-function-pointer only. + * compiler error on 'build(..)' if non-const, static member or non-member function pointer is passed. + */ template template - inline constexpr const Builder RecordBuilder<_recordType>::methodConst(const std::string& pFunction) const + inline constexpr const Builder RecordBuilder<_recordType>::methodConst(const std::string& pFunction) const { return Builder(m_namespace, m_record, pFunction); } + + + /* @method: constructor<...>() + @param: none + @return: ConstructorBuilder<_recordType, _signature...> + * the copy constructors params are detected at compile time only. + * template params <...> - any combination of parameters. + */ template + template + inline constexpr const ConstructorBuilder<_recordType, _signature...> RecordBuilder<_recordType>::constructor() const + { + //this code-block is retained by compiler, if copy constructor with non-const ref('_recordType&') is being registered. + if constexpr (std::is_same_v<_recordType&, typename detail::TypeId<_signature...>::HEAD>) + { + return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::CopyCtor); + } + //this code-block is retained by compiler, if copy constructor with const-ref('const _recordType&') is being registered. + else if constexpr (std::is_same_v::HEAD>) + { + return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::CopyCtorConst); + } + //if any other constructor except, copy constructor is being registered, this code-block will be retained. + else + { + return ConstructorBuilder<_recordType, _signature...>(m_namespace, m_record, FunctorType::Ctor); + } + } } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/Reflect.h b/ReflectionTemplateLib/builder/inc/Reflect.h index 9e18412a..c26d8b80 100644 --- a/ReflectionTemplateLib/builder/inc/Reflect.h +++ b/ReflectionTemplateLib/builder/inc/Reflect.h @@ -6,30 +6,34 @@ namespace rtl { - namespace builder - { - template - class RecordBuilder; + namespace builder + { + template + class RecordBuilder; - // Builder class to encapsulate all type names, pointers. - class Reflect - { - std::string m_record; - std::string m_namespace; + /* @class: Reflect + * provides interface to register all kinds of functions (member/non-member). + */ class Reflect + { + //name of the class, struct being registered as string. + std::string m_record; - public: + //name of the namespace being registered as string. + std::string m_namespace; - Reflect(); - Reflect(const Reflect&) = delete; - Reflect& operator=(const Reflect&) = delete; + public: - Reflect& nameSpace(const std::string& pNamespace); + Reflect(); + Reflect(const Reflect&) = delete; + Reflect& operator=(const Reflect&) = delete; - template - constexpr const Builder function(const std::string& pFunction); + Reflect& nameSpace(const std::string& pNamespace); - template - constexpr const RecordBuilder<_recordType> record(const std::string& pClass); - }; - } + template + constexpr const Builder function(const std::string& pFunction); + + template + constexpr const RecordBuilder<_recordType> record(const std::string& pClass); + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/Reflect.hpp b/ReflectionTemplateLib/builder/inc/Reflect.hpp index bfb0f001..53071dff 100644 --- a/ReflectionTemplateLib/builder/inc/Reflect.hpp +++ b/ReflectionTemplateLib/builder/inc/Reflect.hpp @@ -6,39 +6,68 @@ namespace rtl { - namespace builder - { - inline Reflect::Reflect() - : m_record("") - , m_namespace(NAMESPACE_GLOBAL) { - } + namespace builder + { + inline Reflect::Reflect() + : m_record("") + //If no namespace is given, types are kept under defaultr namespace name: NAMESPACE_GLOBAL. + , m_namespace(NAMESPACE_GLOBAL) { + } - inline Reflect& Reflect::nameSpace(const std::string& pNamespace) - { - m_namespace = pNamespace; - return *this; - } + /* @function: record() + @param: std::string, name of the 'namespace' as string. + @return: 'this', Reflect. + * used to group registered function, class/struct under namespace name. + * its a logical grouping of registered types under a 'namespace' name. + * optional- function, class/struct can be registered without given namespace name, even if they exists in one. + * if types are registered with namespace name, then that name should be passed when retriving the objects from cxxMirror objects. + * check functions CxxMirror::getMethod() & CxxMirror::getFunction(). + */ inline Reflect& Reflect::nameSpace(const std::string& pNamespace) + { + m_namespace = pNamespace; + return *this; + } - template<> - inline const Builder Reflect::function(const std::string& pFunction) - { - return Builder(m_namespace, m_record, pFunction); - } + /* @function: method() + @param: std::string, name of function as string. + @return: Builder + * registers only non-member functions. + * the 'build(..)' called on return object will accepts non-member function pointer only. + * compiler error on 'build(..)' if member function pointer is passed. + */ template<> + inline const Builder Reflect::function(const std::string& pFunction) + { + return Builder(m_namespace, m_record, pFunction); + } - template - inline constexpr const RecordBuilder<_recordType> Reflect::record(const std::string& pClass) - { - return RecordBuilder<_recordType>(m_namespace, pClass); - } + /* @function: record() + @param: std::string, name of class/struct as string. + @return: RecordBuilder<_recordType> + * provides object of 'RecordBuilder', which provides interface to registers member functions of class/struct of '_recordType'. + * the 'build(..)' called on return object will accepts non-member function pointer only. + * compiler error on 'build(..)' if function pointer passed is not a member of class/struct- '_recordType'. + */ template + inline constexpr const RecordBuilder<_recordType> Reflect::record(const std::string& pClass) + { + return RecordBuilder<_recordType>(m_namespace, pClass); + } - template - inline constexpr const Builder Reflect::function(const std::string& pFunction) - { - return Builder(m_namespace, m_record, pFunction); - } - } + /* @method: function<...>() + @param: std::string, name of function as string. + @return: Builder + * registers only non-member functions. + * used for registering overloads, if unique member function, use non-templated version 'function()'. + * template parameters must be explicitly specified, should be exactly same as the function being registered. + * the 'build(..)' called on return object will accepts non-member function pointer only. + * compiler error on 'build(..)' if any member function pointer is passed. + */ template + inline constexpr const Builder Reflect::function(const std::string& pFunction) + { + return Builder(m_namespace, m_record, pFunction); + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/common/Constants.h b/ReflectionTemplateLib/common/Constants.h index 9594e757..29da9294 100644 --- a/ReflectionTemplateLib/common/Constants.h +++ b/ReflectionTemplateLib/common/Constants.h @@ -65,19 +65,19 @@ namespace rtl { struct CtorName { - static const std::string ctor(const std::string& pRecordName) { + static constexpr const std::string ctor(const std::string& pRecordName) { return (pRecordName + "::" + pRecordName + "()"); } - static const std::string dctor(const std::string& pRecordName) { + static constexpr const std::string dctor(const std::string& pRecordName) { return (pRecordName + "::~" + pRecordName + "()"); } - static const std::string copy(const std::string& pRecordName) { + static constexpr const std::string copy(const std::string& pRecordName) { return (pRecordName + "::" + pRecordName + "(" + pRecordName + "&)"); } - static const std::string constCopy(const std::string& pRecordName) { + static constexpr const std::string constCopy(const std::string& pRecordName) { return (pRecordName + "::" + pRecordName + "(const " + pRecordName + "&)"); } }; From eba81f91b6f4be46ddfcdf1c3027742bcced136d Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Sat, 20 Jul 2024 13:07:43 +0530 Subject: [PATCH 6/9] comments added. --- CxxTypeRegistration/src/MyReflection.cpp | 122 ++++++------ ReflectionTemplateLib/access/inc/CxxMirror.h | 59 ++++-- ReflectionTemplateLib/access/inc/Record.h | 56 +++--- .../access/src/CxxMirror.cpp | 129 +++++++----- ReflectionTemplateLib/access/src/Method.cpp | 2 +- ReflectionTemplateLib/access/src/Record.cpp | 175 ++++++++++------- ReflectionTemplateLib/builder/inc/Reflect.h | 2 +- ReflectionTemplateLib/builder/inc/Reflect.hpp | 22 +-- ReflectionTemplateLib/common/Constants.h | 42 ++-- .../detail/inc/CxxReflection.h | 76 ++++---- .../detail/inc/SetupFunction.h | 7 +- .../detail/inc/SetupFunction.hpp | 51 ++--- .../detail/inc/SetupMethod.h | 18 +- .../detail/inc/SetupMethod.hpp | 97 +++------- .../detail/src/CxxReflection.cpp | 183 ++++++++++-------- 15 files changed, 536 insertions(+), 505 deletions(-) diff --git a/CxxTypeRegistration/src/MyReflection.cpp b/CxxTypeRegistration/src/MyReflection.cpp index f03f2f1e..381a3d01 100644 --- a/CxxTypeRegistration/src/MyReflection.cpp +++ b/CxxTypeRegistration/src/MyReflection.cpp @@ -26,65 +26,65 @@ using namespace rtl::builder; CxxMirror& MyReflection::instance() { - static CxxMirror cxxMirror = CxxMirror({ - - //global functions, not contained in any namespace. - Reflect().function(str_reverseString).build(reverseString), //function taking no arguments. '' must be specified if other overload exists else not needed. compiler error otherwise. - Reflect().function(str_reverseString).build(reverseString), //overloaded function, takes 'string' arguments. '' must be specified as template parameter. - Reflect().function(str_reverseString).build(reverseString), //overloaded function, takes 'const char*' arguments. - Reflect().function(str_getComplexNumAsString).build(getComplexNumAsString), //unique function, no overloads, no need to specify signature as template parameters. - - /*Grouping functions under a namespace, which is optional.they can be registered without it as well. - but if registered under namspace, then to retrieve it from CxxMirror object, namespace name must be passed, - ex - cxxMirror.getFunction("namespace_name", "function_name") & cxxMirror.getRecord("namespace_name", "record_name")*/ - Reflect().nameSpace(str_complex).function(str_setReal).build(complex::setReal), - Reflect().nameSpace(str_complex).function(str_setImaginary).build(complex::setImaginary), - Reflect().nameSpace(str_complex).function(str_getMagnitude).build(complex::getMagnitude), - - //Constructors registration, class/struct name and type must be passed 'record("NAME")'. - Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //default constructor. Destructor gets registered automatically if any constructor is registered. - Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //overloaded constructor, taking 'string' as argument, must be specified as template param. - Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //again, the overloaded constructor. - Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //Copy constructor, taking non-const ref as argument. - - //class Calender, default constructor. Instances will always be created on heap and managed using shared_ptr. - Reflect().nameSpace(calender::ns).record(calender::struct_).constructor().build(), - Reflect().record(library::class_).methodStatic(library::str_addBook).build(&Library::addBook), //Static method registration, 'methodStatic()' function must be used. compiler error otherwise. - - //class 'Book', methods & constructors. - Reflect().record(book::class_).constructor().build(), - Reflect().record(book::class_).constructor().build(), //copy constructor, taking const-ref. - Reflect().record(book::class_).constructor().build(), - Reflect().record(book::class_).method(book::str_setAuthor).build(&Book::setAuthor), //unique methods, no overloads. - Reflect().record(book::class_).method(book::str_setDescription).build(&Book::setDescription), - Reflect().record(book::class_).method(book::str_getPublishedOn).build(&Book::getPublishedOn), - Reflect().record(book::class_).method(book::str_updateBookInfo).build(&Book::updateBookInfo), //method overloading, '' must be specified since other overloads exists. - Reflect().record(book::class_).method(book::str_updateBookInfo).build(&Book::updateBookInfo), - Reflect().record(book::class_).method(book::str_updateBookInfo).build(&Book::updateBookInfo), - - //class 'Person', methods & constructors. - Reflect().record(person::class_).constructor().build(), - Reflect().record(person::class_).constructor().build(), - Reflect().record(person::class_).constructor().build(), //copy constructor taking non-const ref argument. - Reflect().record(person::class_).constructor().build(), //copy constructor taking const ref argument. - Reflect().record(person::class_).method(person::str_updateAddress).build(&Person::updateAddress), - Reflect().record(person::class_).method(person::str_updateAddress).build(&Person::updateAddress), - Reflect().record(person::class_).methodConst(person::str_updateLastName).build(&Person::updateLastName), //const method registration, 'methodConst()' function must be used. compiler error otherwise. - Reflect().record(person::class_).methodConst(person::str_updateAddress).build(&Person::updateAddress), - Reflect().record(person::class_).methodConst(person::str_updateAddress).build(&Person::updateAddress), //overloaded method based on 'const'. - Reflect().record(person::class_).methodStatic(person::str_getDefaults).build(&Person::getDefaults), - Reflect().record(person::class_).methodStatic(person::str_getProfile).build(&Person::getProfile), - Reflect().record(person::class_).methodStatic(person::str_getProfile).build(&Person::getProfile), - Reflect().record(person::class_).methodStatic(person::str_getProfile).build(&Person::getProfile) - }); - - - static bool dumped = false; - if (!dumped) { - const std::string pathStr = std::filesystem::current_path().string() + "/MyReflection.json"; - rtl::CxxMirrorToJson::dump(cxxMirror, pathStr); - dumped = true; - } - - return cxxMirror; + static CxxMirror cxxMirror = CxxMirror({ + + //global functions, not contained in any namespace. + Reflect().function(str_reverseString).build(reverseString), //function taking no arguments. '' must be specified if other overload exists else not needed. compiler error otherwise. + Reflect().function(str_reverseString).build(reverseString), //overloaded function, takes 'string' arguments. '' must be specified as template parameter. + Reflect().function(str_reverseString).build(reverseString), //overloaded function, takes 'const char*' arguments. + Reflect().function(str_getComplexNumAsString).build(getComplexNumAsString), //unique function, no overloads, no need to specify signature as template parameters. + + /* Grouping functions under a namespace, which is optional. they can be registered without it as well. + but if registered under namspace, then to retrieve it from CxxMirror object, namespace name must be passed, + ex - cxxMirror.getFunction("namespace_name", "function_name") & cxxMirror.getRecord("namespace_name", "record_name") + */ Reflect().nameSpace(str_complex).function(str_setReal).build(complex::setReal), + Reflect().nameSpace(str_complex).function(str_setImaginary).build(complex::setImaginary), + Reflect().nameSpace(str_complex).function(str_getMagnitude).build(complex::getMagnitude), + + //Constructors registration, class/struct name and type must be passed 'record("NAME")'. + Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //default constructor. Destructor gets registered automatically if any constructor is registered. + Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //overloaded constructor, taking 'string' as argument, must be specified as template param. + Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //again, the overloaded constructor. + Reflect().nameSpace(date::ns).record(date::struct_).constructor().build(), //Copy constructor, taking non-const ref as argument. + + //class Calender, default constructor. Instances will always be created on heap and managed using shared_ptr. + Reflect().nameSpace(calender::ns).record(calender::struct_).constructor().build(), + Reflect().record(library::class_).methodStatic(library::str_addBook).build(&Library::addBook), //Static method registration, 'methodStatic()' function must be used. compiler error otherwise. + + //class 'Book', methods & constructors. + Reflect().record(book::class_).constructor().build(), + Reflect().record(book::class_).constructor().build(), //copy constructor, taking const-ref. + Reflect().record(book::class_).constructor().build(), + Reflect().record(book::class_).method(book::str_setAuthor).build(&Book::setAuthor), //unique methods, no overloads. + Reflect().record(book::class_).method(book::str_setDescription).build(&Book::setDescription), + Reflect().record(book::class_).method(book::str_getPublishedOn).build(&Book::getPublishedOn), + Reflect().record(book::class_).method(book::str_updateBookInfo).build(&Book::updateBookInfo), //method overloading, '' must be specified since other overloads exists. + Reflect().record(book::class_).method(book::str_updateBookInfo).build(&Book::updateBookInfo), + Reflect().record(book::class_).method(book::str_updateBookInfo).build(&Book::updateBookInfo), + + //class 'Person', methods & constructors. + Reflect().record(person::class_).constructor().build(), + Reflect().record(person::class_).constructor().build(), + Reflect().record(person::class_).constructor().build(), //copy constructor taking non-const ref argument. + Reflect().record(person::class_).constructor().build(), //copy constructor taking const ref argument. + Reflect().record(person::class_).method(person::str_updateAddress).build(&Person::updateAddress), + Reflect().record(person::class_).method(person::str_updateAddress).build(&Person::updateAddress), + Reflect().record(person::class_).methodConst(person::str_updateLastName).build(&Person::updateLastName), //const method registration, 'methodConst()' function must be used. compiler error otherwise. + Reflect().record(person::class_).methodConst(person::str_updateAddress).build(&Person::updateAddress), + Reflect().record(person::class_).methodConst(person::str_updateAddress).build(&Person::updateAddress), //overloaded method based on 'const'. + Reflect().record(person::class_).methodStatic(person::str_getDefaults).build(&Person::getDefaults), + Reflect().record(person::class_).methodStatic(person::str_getProfile).build(&Person::getProfile), + Reflect().record(person::class_).methodStatic(person::str_getProfile).build(&Person::getProfile), + Reflect().record(person::class_).methodStatic(person::str_getProfile).build(&Person::getProfile) + }); + + + static bool dumped = false; + if (!dumped) { + const std::string pathStr = std::filesystem::current_path().string() + "/MyReflection.json"; + rtl::CxxMirrorToJson::dump(cxxMirror, pathStr); + dumped = true; + } + + return cxxMirror; } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/CxxMirror.h b/ReflectionTemplateLib/access/inc/CxxMirror.h index ca510167..4b82fefe 100644 --- a/ReflectionTemplateLib/access/inc/CxxMirror.h +++ b/ReflectionTemplateLib/access/inc/CxxMirror.h @@ -8,24 +8,43 @@ namespace rtl { - namespace access - { - class Record; - class Function; - - class CxxMirror : public detail::CxxReflection - { - public: - - CxxMirror(const std::vector& pFunctions); - - std::optional getRecord(const std::string& pFunction); - - std::optional getFunction(const std::string& pFunction); - - std::optional getRecord(const std::string& pNameSpace, const std::string& pFunction); - - std::optional getFunction(const std::string& pNameSpace, const std::string& pFunction); - }; - } + namespace access + { + //forward decls + class Record; + class Function; + + /* @class: CxxMirror + * provides interface to access registered functions/methods by name. + * its the single point of access to whole reflection system. + * all the type registration is done while constructing its object. + * its objects can be createed locally and will be destroyed as regular object, at scope's end. + * deleted copy constructor and assignment operator, can only be passed around as reference or wrapped in a smart pointer. + * the inherited data members are freed upon destruction, except the functors (function/method pointer) tables, they have static lifetime. + * functor tables are not member of this or base class, this class contains 'Function' objects which is a hash-key for looking up a particular functor. + * creating multiple objects of CxxMirror and registring the same functor will not increase the functor tables size. + * once a functor is registered, no entry will be added to the functor table for the same functor, it acts as a set. + * registring the same functor will create duplicate hash-key 'Function' object, which will be ignored if in the same 'CxxMirror' object. + if two different 'CxxMirror' objects are created and registering the same functor, the functor table will have only one entry for the functor + but two duplicate 'Function' objects will be created, held by respective 'CxxMirror' object. + */ class CxxMirror : public detail::CxxReflection + { + public: + + //constructor, taking function objects, other constructors are disabled. + CxxMirror(const std::vector& pFunctions); + + //get the class/struct's member-functions hash-keys wrapped in a 'Record' object. + std::optional getRecord(const std::string& pRecordName) const; + + //get the non-member functions hash-keys. + std::optional getFunction(const std::string& pFunctionName) const; + + //get the class/struct's member-functions hash-keys wrapped in a 'Record' object, registered with a namespace name. + std::optional getRecord(const std::string& pNameSpaceName, const std::string& pRecordName) const; + + //get the non-member functions hash-keys, registered with a namespace name. + std::optional getFunction(const std::string& pNameSpaceName, const std::string& pFunctionName) const; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/Record.h b/ReflectionTemplateLib/access/inc/Record.h index 002dc946..2ae78ae4 100644 --- a/ReflectionTemplateLib/access/inc/Record.h +++ b/ReflectionTemplateLib/access/inc/Record.h @@ -8,42 +8,50 @@ namespace rtl { - namespace detail { - class CxxReflection; - } + //forward decls + namespace detail { + class CxxReflection; + } - namespace access - { - class Method; - class RStatus; - class Instance; + namespace access + { + //forward decls + class Method; + class RStatus; + class Instance; - class Record - { - const std::string m_recordName; + /* @class: Record + * represents a reflected class/struct. + * contains registered member-functions as 'Method' objects. + * provides interface to access methods by name. + * provides interface to construct instances of the class/struct using the registered constructors. + */ class Record + { + const std::string m_recordName; - mutable std::unordered_map< std::string, access::Method > m_methods; + mutable std::unordered_map< std::string, access::Method > m_methods; - Record(const std::string& pRecordName); + Record(const std::string& pRecordName); - std::unordered_map< std::string, access::Method >& getFunctionsMap() const; + std::unordered_map< std::string, access::Method >& getFunctionsMap() const; - public: + public: - Record() = delete; + Record() = delete; - std::optional getMethod(const std::string& pMethod) const; + std::optional getMethod(const std::string& pMethod) const; - //creates dynamic instance, calling copy ctor, using new. - const std::pair clone(Instance& pOther) const; + //creates dynamic instance, calling copy ctor, using new. + const std::pair clone(Instance& pOther) const; - //creates dynamic instance, using new. - template - const std::pair instance(_ctorArgs ...params) const; + //creates dynamic instance, using new. + template + const std::pair instance(_ctorArgs ...params) const; - const std::unordered_map< std::string, access::Method >& getMethodMap() const; + const std::unordered_map< std::string, access::Method >& getMethodMap() const; - friend class detail::CxxReflection; + //only class which can create objects of this class & manipulates 'm_methods'. + friend class detail::CxxReflection; }; } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/src/CxxMirror.cpp b/ReflectionTemplateLib/access/src/CxxMirror.cpp index 6d61b3ae..499844bf 100644 --- a/ReflectionTemplateLib/access/src/CxxMirror.cpp +++ b/ReflectionTemplateLib/access/src/CxxMirror.cpp @@ -7,54 +7,83 @@ namespace rtl { - namespace access - { - CxxMirror::CxxMirror(const std::vector& pFunctions) - : detail::CxxReflection(pFunctions) { - } - - - std::optional CxxMirror::getRecord(const std::string& pRecord) - { - return getRecord(NAMESPACE_GLOBAL, pRecord); - } - - - std::optional CxxMirror::getFunction(const std::string& pFunction) - { - return getFunction(NAMESPACE_GLOBAL, pFunction); - } - - - std::optional CxxMirror::getRecord(const std::string& pNameSpace, const std::string& pRecord) - { - const auto& nsRecordMap = getNamespaceRecordMap(); - const auto& itr = nsRecordMap.find(pNameSpace); - if (itr != nsRecordMap.end()) - { - const auto& recordMap = itr->second; - const auto& itr0 = recordMap.find(pRecord); - if (itr0 != recordMap.end()) { - return std::make_optional(itr0->second); - } - } - return std::nullopt; - } - - - std::optional CxxMirror::getFunction(const std::string& pNameSpace, const std::string& pFunction) - { - const auto& nsFunctionMap = getNamespaceFunctionsMap(); - const auto& itr = nsFunctionMap.find(pNameSpace); - if (itr != nsFunctionMap.end()) - { - const auto& functionMap = itr->second; - const auto& itr0 = functionMap.find(pFunction); - if (itr0 != functionMap.end()) { - return std::make_optional(itr0->second); - } - } - return std::nullopt; - } - } + namespace access + { + /* @Constructor: CxxMirror + @params: 'const std::vector&' + * accepts vector of 'Function' objects, which are hash-key to lookup a functor. + * the only constructor to construct 'CxxMirror' object. + * Syntax for constructing - CxxMirror({ Reflect().function("func_name").build(), ..., ... }) + * '.build()' function will return a 'Function' object, and passed to std::vector initializer list. + * the vector is simply forwarded to the base class constructor. + */ CxxMirror::CxxMirror(const std::vector& pFunctions) + : detail::CxxReflection(pFunctions) { + } + + + /* @method: getRecord + @param: const std::string& (name of the class/struct) + @return: std::optional + * if the class/struct isn't found by the given name, std::nullopt is returned. + * every class/struct's is grouped under a namespace. + * if no namespace is specified while registration, NAMESPACE_GLOBAL is used. + */ std::optional CxxMirror::getRecord(const std::string& pRecord) const + { + return getRecord(NAMESPACE_GLOBAL, pRecord); + } + + + /* @method: getFunction + @param: const std::string& (name of the non-member function) + @return: std::optional + * if the function isn't found by the given name, std::nullopt is returned. + * every function is grouped under a namespace. + * if no namespace is specified while registration, NAMESPACE_GLOBAL is used. + */ std::optional CxxMirror::getFunction(const std::string& pFunction) const + { + return getFunction(NAMESPACE_GLOBAL, pFunction); + } + + + /* @method: getRecord + @param: std::string (namespace name), std::string (class/struct name) + @return: std::optional + * retrieves the class/struct (as Record) registered under the given namespace. + * if the class/struct isn't found by the given name, std::nullopt is returned. + */ std::optional CxxMirror::getRecord(const std::string& pNameSpace, const std::string& pRecord) const + { + const auto& nsRecordMap = getNamespaceRecordMap(); + const auto& itr = nsRecordMap.find(pNameSpace); + if (itr != nsRecordMap.end()) + { + const auto& recordMap = itr->second; + const auto& itr0 = recordMap.find(pRecord); + if (itr0 != recordMap.end()) { + return std::make_optional(itr0->second); + } + } + return std::nullopt; + } + + + /* @method: getFunction + @param: namespace name (std::string), non-mermber function name (std::string) + @return: std::optional + * retrieves the function (as 'Function' object) registered under the given namespace. + * if the function isn't found by the given name, std::nullopt is returned. + */ std::optional CxxMirror::getFunction(const std::string& pNameSpace, const std::string& pFunction) const + { + const auto& nsFunctionMap = getNamespaceFunctionsMap(); + const auto& itr = nsFunctionMap.find(pNameSpace); + if (itr != nsFunctionMap.end()) + { + const auto& functionMap = itr->second; + const auto& itr0 = functionMap.find(pFunction); + if (itr0 != functionMap.end()) { + return std::make_optional(itr0->second); + } + } + return std::nullopt; + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/src/Method.cpp b/ReflectionTemplateLib/access/src/Method.cpp index 28d8aaa1..89e2f06a 100644 --- a/ReflectionTemplateLib/access/src/Method.cpp +++ b/ReflectionTemplateLib/access/src/Method.cpp @@ -6,7 +6,7 @@ namespace rtl { namespace access { Method::Method(const Function& pFunction) - :Function(pFunction) { + : Function(pFunction) { } diff --git a/ReflectionTemplateLib/access/src/Record.cpp b/ReflectionTemplateLib/access/src/Record.cpp index 0c773576..f304a0ec 100644 --- a/ReflectionTemplateLib/access/src/Record.cpp +++ b/ReflectionTemplateLib/access/src/Record.cpp @@ -8,83 +8,122 @@ namespace rtl { - namespace access - { - Record::Record(const std::string& pRecordName) - : m_recordName(pRecordName) - { - } + namespace access + { + Record::Record(const std::string& pRecordName) + : m_recordName(pRecordName) + { + } - std::unordered_map< std::string, access::Method >& Record::getFunctionsMap() const - { - return m_methods; - } + /* @method: getFunctionsMap + @param: none + @return: std::unordered_map< std::string, access::Method >& + * get set of all registered methods contained by the class/struct represented by this 'Record'. + * provides 'mutable' map, which only detail::CxxReflection class can access. + */ std::unordered_map< std::string, access::Method >& Record::getFunctionsMap() const + { + return m_methods; + } - const std::unordered_map& Record::getMethodMap() const - { - return m_methods; - } + /* @method: getMethodMap + @param: none + @return: const std::unordered_map< std::string, access::Method >& + * get set of all registered methods contained by the class/struct represented by this 'Record'. + * provides 'const' map, publicly accessible. + */ const std::unordered_map& Record::getMethodMap() const + { + return m_methods; + } - std::optional Record::getMethod(const std::string& pMethod) const - { - const auto& itr = m_methods.find(pMethod); - if (itr != m_methods.end()) { - return std::optional(itr->second); - } - return std::nullopt; - } + /* @method: getMethod + @param: const std::string& (name of the method) + @return: std::optional + * if the method isn't found by the given name, std::nullopt is returned. + */ std::optional Record::getMethod(const std::string& pMethod) const + { + const auto& itr = m_methods.find(pMethod); + if (itr != m_methods.end()) { + return std::optional(itr->second); + } + return std::nullopt; + } - const std::pair Record::clone(Instance& pOther) const - { - if (pOther.isEmpty()) { - return std::make_pair(RStatus(Error::EmptyInstance), Instance()); - } + /* @method: clone + @param: Instance& (containing class/struct's object represented by this 'Record') + @return: std::pair (RStatus: call success or not, Instance: containing copy constructed object) + * calls copy constructor of class/struct represented by this 'Record' + * creates copy of the object wrapped inside 'Instance' object. + * returns 'RStatus' object indicating the success of the reflection call with other infos. + */ const std::pair Record::clone(Instance& pOther) const + { + //validate the source object, should not be empty. + if (pOther.isEmpty()) { + //return empty instance with error status. + return std::make_pair(RStatus(Error::EmptyInstance), Instance()); + } - const std::string& dctor = CtorName::dctor(m_recordName); - const std::string& copyStr = CtorName::copy(m_recordName); - const std::string& constCopyStr = CtorName::constCopy(m_recordName); + const std::string& dctor = CtorName::dctor(m_recordName); + const std::string& copyStr = CtorName::copy(m_recordName); + const std::string& constCopyStr = CtorName::constCopy(m_recordName); - std::optional destructor = getMethod(dctor); - std::optional constCopyCtor = getMethod(constCopyStr); + std::optional destructor = getMethod(dctor); + std::optional constCopyCtor = getMethod(constCopyStr); - if (pOther.isConst()) - { - if (constCopyCtor) - { - if (constCopyCtor->getRecordTypeId() != pOther.getTypeId()) { - return std::make_pair(RStatus(Error::InstanceTypeMismatch), Instance()); - } - RStatus status = (*constCopyCtor)(pOther.get()); - return std::make_pair(status, Instance(status.getReturn(), status, *destructor)); - } - else { - return std::make_pair(RStatus(Error::ConstCopyConstructorNotFound), Instance()); - } - } - else { - std::optional copyCtor = getMethod(copyStr); - if (copyCtor) - { - if (copyCtor->getRecordTypeId() != pOther.getTypeId()) { - return std::make_pair(RStatus(Error::InstanceTypeMismatch), Instance()); - } - RStatus status = (*copyCtor)(pOther.get()); - return std::make_pair(status, Instance(status.getReturn(), status, *destructor)); - } - else if (constCopyCtor) - { - if (constCopyCtor->getRecordTypeId() != pOther.getTypeId()) { - return std::make_pair(RStatus(Error::InstanceTypeMismatch), Instance()); - } - RStatus status = (*constCopyCtor)(pOther.get()); - return std::make_pair(status, Instance(status.getReturn(), status, *destructor)); - } - } - return std::make_pair(RStatus(Error::CopyConstructorNotFound), Instance()); - } - } + //if the object is const, only copy constructor with 'const&' can be called on it. + if (pOther.isConst()) + { + if (constCopyCtor) + { + /* type of the object wrapped inder source 'Instance' should match with type of the class/struct + associated by constructor ('Function')object. + */ if (constCopyCtor->getRecordTypeId() != pOther.getTypeId()) { + //if source instance & ctor type didn't match, return empty instance with error status. + return std::make_pair(RStatus(Error::InstanceTypeMismatch), Instance()); + } + //object and type validated. call the const-copy-constructor. + RStatus status = (*constCopyCtor)(pOther.get()); + return std::make_pair(status, Instance(status.getReturn(), status, *destructor)); + } + else { + //if the object is 'const' and no constructor found accepting 'const&' + return std::make_pair(RStatus(Error::ConstCopyConstructorNotFound), Instance()); + } + } + else { + //if the source 'Instance' is non-const, find copy-constructor taking non-const ref. + std::optional copyCtor = getMethod(copyStr); + if (copyCtor) + { + /* type of the object wrapped inder source 'Instance' should match with type of the class/struct + associated by constructor ('Function')object. + */ if (copyCtor->getRecordTypeId() != pOther.getTypeId()) { + //if source instance & ctor type didn't match, return empty instance with error status. + return std::make_pair(RStatus(Error::InstanceTypeMismatch), Instance()); + } + //object and type validated. call the non-const-copy-constructor. + RStatus status = (*copyCtor)(pOther.get()); + return std::make_pair(status, Instance(status.getReturn(), status, *destructor)); + } + //if copy-constructor taking non-const ref not found, and with const-ref found, use that copy constructor. + else if (constCopyCtor) + { + /* type of the object wrapped inder source 'Instance' should match with type of the class/struct + associated by constructor ('Function')object. + */ if (constCopyCtor->getRecordTypeId() != pOther.getTypeId()) { + //if source instance & ctor type didn't match, return empty instance with error status. + return std::make_pair(RStatus(Error::InstanceTypeMismatch), Instance()); + } + //object and type validated. call the const-copy-constructor. + RStatus status = (*constCopyCtor)(pOther.get()); + return std::make_pair(status, Instance(status.getReturn(), status, *destructor)); + } + } + //if no registered copy constructor found, return empty instance with error status. + return std::make_pair(RStatus(Error::CopyConstructorNotFound), Instance()); + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/Reflect.h b/ReflectionTemplateLib/builder/inc/Reflect.h index c26d8b80..291b9188 100644 --- a/ReflectionTemplateLib/builder/inc/Reflect.h +++ b/ReflectionTemplateLib/builder/inc/Reflect.h @@ -18,7 +18,7 @@ namespace rtl { //name of the class, struct being registered as string. std::string m_record; - //name of the namespace being registered as string. + //name of the namespace being registered as string. std::string m_namespace; public: diff --git a/ReflectionTemplateLib/builder/inc/Reflect.hpp b/ReflectionTemplateLib/builder/inc/Reflect.hpp index 53071dff..99d858a4 100644 --- a/ReflectionTemplateLib/builder/inc/Reflect.hpp +++ b/ReflectionTemplateLib/builder/inc/Reflect.hpp @@ -10,19 +10,19 @@ namespace rtl { { inline Reflect::Reflect() : m_record("") - //If no namespace is given, types are kept under defaultr namespace name: NAMESPACE_GLOBAL. + //If no namespace is given, types are kept under default namespace name: NAMESPACE_GLOBAL. , m_namespace(NAMESPACE_GLOBAL) { } - /* @function: record() + /* @function: nameSpace() @param: std::string, name of the 'namespace' as string. - @return: 'this', Reflect. - * used to group registered function, class/struct under namespace name. + @return: '*this', Reflect. + * used to group registered function, class/struct under namespace name. * its a logical grouping of registered types under a 'namespace' name. * optional- function, class/struct can be registered without given namespace name, even if they exists in one. * if types are registered with namespace name, then that name should be passed when retriving the objects from cxxMirror objects. - * check functions CxxMirror::getMethod() & CxxMirror::getFunction(). + * check functions CxxMirror::getFunction("name_space", "func_name") & CxxMirror::getFunction("name_space","class_name"). */ inline Reflect& Reflect::nameSpace(const std::string& pNamespace) { m_namespace = pNamespace; @@ -30,11 +30,11 @@ namespace rtl { } - /* @function: method() + /* @function: function() @param: std::string, name of function as string. @return: Builder - * registers only non-member functions. - * the 'build(..)' called on return object will accepts non-member function pointer only. + * registers only non-member functions. + * the 'build(..)' called on return object accepts non-member function pointer only. * compiler error on 'build(..)' if member function pointer is passed. */ template<> inline const Builder Reflect::function(const std::string& pFunction) @@ -46,8 +46,8 @@ namespace rtl { /* @function: record() @param: std::string, name of class/struct as string. @return: RecordBuilder<_recordType> - * provides object of 'RecordBuilder', which provides interface to registers member functions of class/struct of '_recordType'. - * the 'build(..)' called on return object will accepts non-member function pointer only. + * provides object of 'RecordBuilder', which provides interface to registers member functions of class/struct of '_recordType'. + * the 'build(..)' called on return object accepts non-member function pointer only. * compiler error on 'build(..)' if function pointer passed is not a member of class/struct- '_recordType'. */ template inline constexpr const RecordBuilder<_recordType> Reflect::record(const std::string& pClass) @@ -62,7 +62,7 @@ namespace rtl { * registers only non-member functions. * used for registering overloads, if unique member function, use non-templated version 'function()'. * template parameters must be explicitly specified, should be exactly same as the function being registered. - * the 'build(..)' called on return object will accepts non-member function pointer only. + * the 'build(..)' called on return object accepts non-member function pointer only. * compiler error on 'build(..)' if any member function pointer is passed. */ template inline constexpr const Builder Reflect::function(const std::string& pFunction) diff --git a/ReflectionTemplateLib/common/Constants.h b/ReflectionTemplateLib/common/Constants.h index 29da9294..3ae4fc51 100644 --- a/ReflectionTemplateLib/common/Constants.h +++ b/ReflectionTemplateLib/common/Constants.h @@ -41,44 +41,34 @@ namespace rtl { constexpr const char* NAMESPACE_GLOBAL = "namespace_global"; -#define GETTER(_varType, _name, _var) \ - inline constexpr const _varType& get##_name() const { \ - return _var; \ - } - -#define GETTER_REF(_varType, _name, _var) \ - inline _varType& get##_name() const { \ - return _var; \ - } - - template - using enable_if_void = typename std::enable_if< std::is_same<_type, void>::value >::type; - - template - using enable_if_non_void = typename std::enable_if< !std::is_same<_type, void>::value >::type; - - template - using enable_if_same = typename std::enable_if< std::is_same<_typeA, _typeB>::value >::type; - - template - using enable_if_not_same = typename std::enable_if< !std::is_same<_type, _typeB>::value >::type; - struct CtorName { - static constexpr const std::string ctor(const std::string& pRecordName) { + static const std::string ctor(const std::string& pRecordName) { return (pRecordName + "::" + pRecordName + "()"); } - static constexpr const std::string dctor(const std::string& pRecordName) { + static const std::string dctor(const std::string& pRecordName) { return (pRecordName + "::~" + pRecordName + "()"); } - static constexpr const std::string copy(const std::string& pRecordName) { + static const std::string copy(const std::string& pRecordName) { return (pRecordName + "::" + pRecordName + "(" + pRecordName + "&)"); } - static constexpr const std::string constCopy(const std::string& pRecordName) { + static const std::string constCopy(const std::string& pRecordName) { return (pRecordName + "::" + pRecordName + "(const " + pRecordName + "&)"); } }; + + +#define GETTER(_varType, _name, _var) \ + inline constexpr const _varType& get##_name() const { \ + return _var; \ + } + + +#define GETTER_REF(_varType, _name, _var) \ + inline _varType& get##_name() const { \ + return _var; \ + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/CxxReflection.h b/ReflectionTemplateLib/detail/inc/CxxReflection.h index 0de40d63..3ef39c6e 100644 --- a/ReflectionTemplateLib/detail/inc/CxxReflection.h +++ b/ReflectionTemplateLib/detail/inc/CxxReflection.h @@ -8,47 +8,57 @@ namespace rtl { - namespace access - { - class Record; - class Method; - class Function; - } + namespace access + { + //Forward decls. + class Record; + class Method; + class Function; + } - namespace detail - { - class CxxReflection - { - using RecordMap = std::unordered_map ; - using MethodMap = std::unordered_map ; - using FunctionMap = std::unordered_map ; + namespace detail + { + /* @class: CxxReflection + * base class for main 'CxxMirror' interface. + * accepts 'Function' objects for construction, frowared from 'CxxMirror' constructor + * organizes the 'Function' objects by namespace, class/structs. + */ class CxxReflection + { + using RecordMap = std::unordered_map ; + using MethodMap = std::unordered_map ; + using FunctionMap = std::unordered_map ; - std::unordered_map m_nsRecordsMap; - std::unordered_map m_nsFunctionsMap; + //contains 'Record' (class/struct) objects, mapped with given namespace name. + std::unordered_map m_nsRecordsMap; - void organizeFunctorsMetaData(const access::Function& pFunction); + //contains 'Function' (non-member-function) objects, mapped with given namespace name. + std::unordered_map m_nsFunctionsMap; - void addRecord(RecordMap& pRecordMap, const access::Function& pFunction); - void addMethod(MethodMap& pMethodMap, const access::Function& pFunction); - void addFunction(FunctionMap& pFunctionMap, const access::Function& pFunction); + void organizeFunctorsMetaData(const access::Function& pFunction); - protected: + void addRecord(RecordMap& pRecordMap, const access::Function& pFunction); + void addMethod(MethodMap& pMethodMap, const access::Function& pFunction); + void addFunction(FunctionMap& pFunctionMap, const access::Function& pFunction); - CxxReflection() = delete; - CxxReflection(CxxReflection&) = delete; - CxxReflection& operator=(CxxReflection&) = delete; + protected: - CxxReflection(const std::vector& pFunctions); + CxxReflection() = delete; + CxxReflection(CxxReflection&) = delete; + CxxReflection& operator=(CxxReflection&) = delete; - public: + CxxReflection(const std::vector& pFunctions); - constexpr const std::unordered_map& getNamespaceRecordMap() { - return m_nsRecordsMap; - } + public: - constexpr const std::unordered_map& getNamespaceFunctionsMap() { - return m_nsFunctionsMap; - } - }; - } + //returns the complete map of registered methods grouped by namespace, contained in 'Record' (class/struct) objects. + constexpr const std::unordered_map& getNamespaceRecordMap() const { + return m_nsRecordsMap; + } + + //returns the complete map of registered functions ('Function' objects) under a namespace. + constexpr const std::unordered_map& getNamespaceFunctionsMap() const { + return m_nsFunctionsMap; + } + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupFunction.h b/ReflectionTemplateLib/detail/inc/SetupFunction.h index ab554486..9bdea470 100644 --- a/ReflectionTemplateLib/detail/inc/SetupFunction.h +++ b/ReflectionTemplateLib/detail/inc/SetupFunction.h @@ -12,12 +12,7 @@ namespace rtl { protected: template - static const detail::FunctorId addFunctor(_returnType(*pFunctor)(_signature...), - enable_if_void<_returnType> *_= nullptr); - - template - static const detail::FunctorId addFunctor(_returnType(*pFunctor)(_signature...), - enable_if_non_void<_returnType> *_= nullptr); + static const detail::FunctorId addFunctor(_returnType(*pFunctor)(_signature...)); }; } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupFunction.hpp b/ReflectionTemplateLib/detail/inc/SetupFunction.hpp index 28676cc5..7feed032 100644 --- a/ReflectionTemplateLib/detail/inc/SetupFunction.hpp +++ b/ReflectionTemplateLib/detail/inc/SetupFunction.hpp @@ -8,8 +8,7 @@ namespace rtl { template template - inline const detail::FunctorId SetupFunction<_derivedType>::addFunctor(_returnType(*pFunctor)(_signature...), - enable_if_void<_returnType> *_) + inline const detail::FunctorId SetupFunction<_derivedType>::addFunctor(_returnType(*pFunctor)(_signature...)) { static std::vector> functorSet; const auto& updateIndex = [&](const std::size_t& pIndex) { @@ -24,47 +23,23 @@ namespace rtl return -1; }; - const auto& functor = [=](_signature...params)->access::RStatus - { - (*pFunctor)(params...); - return access::RStatus(Error::None); - }; - - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<_returnType>::get(), TypeId<>::None, _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_returnType>()); - } - - - template - template - inline const detail::FunctorId SetupFunction<_derivedType>::addFunctor(_returnType(*pFunctor)(_signature...), - enable_if_non_void<_returnType> *_) - { - static std::vector> functorSet; - const auto& updateIndex = [&](const std::size_t& pIndex) { - functorSet.emplace_back(pFunctor, pIndex); - }; - const auto& getIndex = [&]()->const std::size_t { - for (const auto& fptr : functorSet) { - if (fptr.first == pFunctor) { - return fptr.second; - } - } - return -1; - }; - - const auto& typeId = TypeId<_returnType>::get(); + const auto& retTypeId = TypeId<_returnType>::get(); const auto functor = [=](_signature...params)->access::RStatus { - const _returnType& retObj = (*pFunctor)(params...); - const TypeQ& qualifier = std::is_const<_returnType>::value ? TypeQ::Const : TypeQ::Mute; - return access::RStatus(std::make_any<_returnType>(retObj), typeId, qualifier); + if constexpr (std::is_same_v<_returnType, void>) { + (*pFunctor)(params...); + return access::RStatus(Error::None); + } + else { + const _returnType& retObj = (*pFunctor)(params...); + const TypeQ& qualifier = std::is_const<_returnType>::value ? TypeQ::Const : TypeQ::Mute; + return access::RStatus(std::make_any<_returnType>(retObj), retTypeId, qualifier); + } }; const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<_returnType>::get(), TypeId<>::None, _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_returnType>()); + return detail::FunctorId(index, retTypeId, TypeId<>::None, _derivedType::getContainerId(), + _derivedType::template getSignatureStr<_returnType>()); } } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupMethod.h b/ReflectionTemplateLib/detail/inc/SetupMethod.h index c317cf69..4f8f81d2 100644 --- a/ReflectionTemplateLib/detail/inc/SetupMethod.h +++ b/ReflectionTemplateLib/detail/inc/SetupMethod.h @@ -4,28 +4,18 @@ namespace rtl { - namespace detail + namespace detail { template - class SetupMethod + class SetupMethod { protected: template - static const detail::FunctorId addFunctor(_retType(_recordType::* pFunctor)(_signature...), - enable_if_void<_retType> *_= nullptr); + static const detail::FunctorId addFunctor(_retType(_recordType::* pFunctor)(_signature...)); template - static const detail::FunctorId addFunctor(_retType(_recordType::* pFunctor)(_signature...), - enable_if_non_void<_retType> *_= nullptr); - - template - static const detail::FunctorId addFunctor(_retType(_recordType::* pFunctor)(_signature...) const, - enable_if_void<_retType> *_= nullptr); - - template - static const detail::FunctorId addFunctor(_retType(_recordType::* pFunctor)(_signature...) const, - enable_if_non_void<_retType> *_= nullptr); + static const detail::FunctorId addFunctor(_retType(_recordType::* pFunctor)(_signature...) const); }; } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupMethod.hpp b/ReflectionTemplateLib/detail/inc/SetupMethod.hpp index 49a2b093..09788516 100644 --- a/ReflectionTemplateLib/detail/inc/SetupMethod.hpp +++ b/ReflectionTemplateLib/detail/inc/SetupMethod.hpp @@ -4,45 +4,13 @@ #include "TypeId.hpp" #include "SetupMethod.h" -namespace rtl +namespace rtl { namespace detail { template template - inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...), - enable_if_void<_retType> *_) - { - static std::vector> functorSet; - const auto& updateIndex = [&](const std::size_t& pIndex) { - functorSet.emplace_back(pFunctor, pIndex); - }; - const auto& getIndex = [&]()->const std::size_t { - for (const auto& fptr : functorSet) { - if (fptr.first == pFunctor) { - return fptr.second; - } - } - return -1; - }; - - const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus - { - _recordType* target = std::any_cast<_recordType*>(pTargetObj); - (target->*pFunctor)(params...); - return access::RStatus(Error::None); - }; - - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<_retType>::get(), TypeId<_recordType>::get(), _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType, _retType>()); - } - - - template - template - inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...), - enable_if_non_void<_retType> *_) + inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...)) { static std::vector> functorSet; const auto& updateIndex = [&](const std::size_t& pIndex) { @@ -61,52 +29,27 @@ namespace rtl const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus { _recordType* target = std::any_cast<_recordType*>(pTargetObj); - const _retType& retObj = (target->*pFunctor)(params...); - const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; - return access::RStatus(std::make_any<_retType>(retObj), retTypeId, qualifier); - }; - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, retTypeId, TypeId<_recordType>::get(), _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType, _retType>()); - } - - - template - template - inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...) const, - enable_if_void<_retType> *_) - { - static std::vector> functorSet; - const auto& updateIndex = [&](const std::size_t& pIndex) { - functorSet.emplace_back(pFunctor, pIndex); - }; - const auto& getIndex = [&]()->const std::size_t { - for (const auto& fptr : functorSet) { - if (fptr.first == pFunctor) { - return fptr.second; - } + if constexpr (std::is_same_v<_retType, void>) { + (target->*pFunctor)(params...); + return access::RStatus(Error::None); + } + else { + const _retType& retObj = (target->*pFunctor)(params...); + const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; + return access::RStatus(std::make_any<_retType>(retObj), retTypeId, qualifier); } - return -1; - }; - - const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus - { - _recordType* target = std::any_cast<_recordType*>(pTargetObj); - ((static_cast(target))->*pFunctor)(params...); - return access::RStatus(Error::None); }; const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<_retType>::get(), TypeId<_recordType>::get(), _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType, _retType>()); + return detail::FunctorId(index, retTypeId, TypeId<_recordType>::get(), _derivedType::getContainerId(), + _derivedType::template getSignatureStr<_recordType, _retType>()); } template template - inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...) const, - enable_if_non_void<_retType> *_) + inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...) const) { static std::vector> functorSet; const auto& updateIndex = [&](const std::size_t& pIndex) { @@ -126,14 +69,20 @@ namespace rtl const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus { _recordType* target = std::any_cast<_recordType*>(pTargetObj); - const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; - const _retType& retObj = ((static_cast(target))->*pFunctor)(params...); - return access::RStatus(std::make_any<_retType>(retObj), retTypeId, constRetTypeId, qualifier); + if constexpr (std::is_same_v<_retType, void>) { + ((static_cast(target))->*pFunctor)(params...); + return access::RStatus(Error::None); + } + else { + const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; + const _retType& retObj = ((static_cast(target))->*pFunctor)(params...); + return access::RStatus(std::make_any<_retType>(retObj), retTypeId, constRetTypeId, qualifier); + } }; const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); return detail::FunctorId(index, retTypeId, TypeId<_recordType>::get(), _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType, _retType>()); + _derivedType::template getSignatureStr<_recordType, _retType>()); } } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/src/CxxReflection.cpp b/ReflectionTemplateLib/detail/src/CxxReflection.cpp index d6092093..166ef8b5 100644 --- a/ReflectionTemplateLib/detail/src/CxxReflection.cpp +++ b/ReflectionTemplateLib/detail/src/CxxReflection.cpp @@ -6,93 +6,120 @@ namespace rtl { - namespace detail - { - CxxReflection::CxxReflection(const std::vector& pFunctions) - { - for (const auto& function : pFunctions) { - organizeFunctorsMetaData(function); + namespace detail + { + /* @Constructor: CxxMirror + @params: 'const std::vector&' + * recieves vector of 'Function' objects, forwarded from 'CxxMirror' constructor. + * initiates grouping of each 'Function' object under namespace, class/struct. + */ CxxReflection::CxxReflection(const std::vector& pFunctions) + { + for (const auto& function : pFunctions) { + organizeFunctorsMetaData(function); } } - void CxxReflection::addRecord(RecordMap& pRecordMap, const access::Function& pFunction) - { - const auto& recordName = pFunction.getRecordName(); - const auto& itr = pRecordMap.find(recordName); - if (itr == pRecordMap.end()) { - const auto& recordItr = pRecordMap.emplace(recordName, access::Record(recordName)); - addMethod(recordItr.first->second.getFunctionsMap(),pFunction); - } - else { - addMethod(itr->second.getFunctionsMap(), pFunction); - } - } + /* @method: addRecord + @params: RecordMap, Function + * constructs the 'Record'(class/struct) object & adds 'Function' as 'Method' to it. + * if the 'Record' already exists in the map, the 'Function' object is added as 'Method' to it. + */ void CxxReflection::addRecord(RecordMap& pRecordMap, const access::Function& pFunction) + { + const auto& recordName = pFunction.getRecordName(); + const auto& itr = pRecordMap.find(recordName); + if (itr == pRecordMap.end()) { + const auto& recordItr = pRecordMap.emplace(recordName, access::Record(recordName)); + addMethod(recordItr.first->second.getFunctionsMap(),pFunction); + } + else { + addMethod(itr->second.getFunctionsMap(), pFunction); + } + } - void CxxReflection::addFunction(FunctionMap& pFunctionMap, const access::Function& pFunction) - { - const auto& fname = pFunction.getFunctionName(); - const auto& itr = pFunctionMap.find(fname); - if (itr == pFunctionMap.end()) { - pFunctionMap.emplace(fname, pFunction); - } - else { - const auto& function = itr->second; - function.addOverload(pFunction); - } - } + /* @method: addFunction + @params: FunctionMap, Function + * adds the 'Function' object as non-member function mapped to the given namespace name. + */ void CxxReflection::addFunction(FunctionMap& pFunctionMap, const access::Function& pFunction) + { + const auto& fname = pFunction.getFunctionName(); + const auto& itr = pFunctionMap.find(fname); + if (itr == pFunctionMap.end()) { + pFunctionMap.emplace(fname, pFunction); + } + else { + const auto& function = itr->second; + //if the function is already present, add its 'FunctorId' as overload. + function.addOverload(pFunction); + } + } - void CxxReflection::addMethod(MethodMap& pMethodMap, const access::Function& pFunction) - { - const auto& fname = pFunction.getFunctionName(); - const auto& itr = pMethodMap.find(fname); - if (itr == pMethodMap.end()) - { - auto& functorIds = pFunction.getFunctorIds(); - if (functorIds.size() > 1) - { - const auto& dctorName = CtorName::dctor(pFunction.getRecordName()); - if (pMethodMap.find(dctorName) == pMethodMap.end()) { - access::Method method = access::Method::getDestructorMethod(pFunction, functorIds[1]); - pMethodMap.insert(std::make_pair(method.getFunctionName(), method)); - } - functorIds.pop_back(); - } - pMethodMap.emplace(fname, access::Method(pFunction)); - } - else { - const auto& function = itr->second; - function.addOverload(pFunction); - } - } + /* @method: addMethod + @params: MethodMap, Function + * adds the 'Function' object as 'Method' object the the method map contained by 'Record' object. + * if the function name already exists in the map, then 'FunctorId' from the source 'Function' object is added to already existing 'Function' object. + * if a 'Function' object represents a Constructor, it might have the destructor 'FunctorId' as well. + * if destructor 'FunctorId' is found, destructor 'Function' object is created and added to the 'MethodMap'. + */ void CxxReflection::addMethod(MethodMap& pMethodMap, const access::Function& pFunction) + { + const auto& fname = pFunction.getFunctionName(); + const auto& itr = pMethodMap.find(fname); + if (itr == pMethodMap.end()) + { + auto& functorIds = pFunction.getFunctorIds(); + /* This condition will be true only in case that 'Function' object represents a constructor + and has more that one 'FunctorId'. every other function registered will have only one 'FunctorId'. + */ if (functorIds.size() > 1) + { + const auto& dctorName = CtorName::dctor(pFunction.getRecordName()); + if (pMethodMap.find(dctorName) == pMethodMap.end()) { + //destructor 'FunctorId' will always be the second in the constructor's FunctorId's vector. + access::Method method = access::Method::getDestructorMethod(pFunction, functorIds[1]); + pMethodMap.insert(std::make_pair(method.getFunctionName(), method)); + } + //remove the destructor 'FunctorId' from the constructor's 'FunctorId' vector. + functorIds.pop_back(); + } + //construct 'Method' obejct from 'Function' object and add. + pMethodMap.emplace(fname, access::Method(pFunction)); + } + else { + const auto& function = itr->second; + //if the method is already present, add as overload. + function.addOverload(pFunction); + } + } - void CxxReflection::organizeFunctorsMetaData(const access::Function& pFunction) - { - const auto& nameSpace = pFunction.getNamespace(); + /* @method: organizeFunctorsMetaData + @params: Function + * seggregates all the 'Function' objects and builds 'Record' & 'Method' objects. + */ void CxxReflection::organizeFunctorsMetaData(const access::Function& pFunction) + { + const auto& nameSpace = pFunction.getNamespace(); - if (pFunction.getRecordName().empty()) { - const auto& itr = m_nsFunctionsMap.find(nameSpace); - if (itr == m_nsFunctionsMap.end()) { - const auto& funcMapItr = m_nsFunctionsMap.emplace(nameSpace, FunctionMap()); - addFunction(funcMapItr.first->second, pFunction); - } - else { - addFunction(itr->second, pFunction); - } - } - else { - const auto& itr = m_nsRecordsMap.find(nameSpace); - if (itr == m_nsRecordsMap.end()) { - const auto& recordMapItr = m_nsRecordsMap.emplace(nameSpace, RecordMap()); - addRecord(recordMapItr.first->second, pFunction); - } - else { - addRecord(itr->second, pFunction); - } - } - } - } + if (pFunction.getRecordName().empty()) { + const auto& itr = m_nsFunctionsMap.find(nameSpace); + if (itr == m_nsFunctionsMap.end()) { + const auto& funcMapItr = m_nsFunctionsMap.emplace(nameSpace, FunctionMap()); + addFunction(funcMapItr.first->second, pFunction); + } + else { + addFunction(itr->second, pFunction); + } + } + else { + const auto& itr = m_nsRecordsMap.find(nameSpace); + if (itr == m_nsRecordsMap.end()) { + const auto& recordMapItr = m_nsRecordsMap.emplace(nameSpace, RecordMap()); + addRecord(recordMapItr.first->second, pFunction); + } + else { + addRecord(itr->second, pFunction); + } + } + } + } } \ No newline at end of file From 44effdf007a57c49f9b4fed530c62644d500af09 Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Sat, 20 Jul 2024 19:28:48 +0530 Subject: [PATCH 7/9] comments added. --- ReflectionTemplateLib/access/inc/Function.h | 90 +++++++----- ReflectionTemplateLib/access/inc/Function.hpp | 38 +++-- ReflectionTemplateLib/access/inc/Instance.h | 1 - ReflectionTemplateLib/access/inc/RStatus.h | 86 ++++++----- ReflectionTemplateLib/access/inc/Record.hpp | 63 +++++--- .../access/src/CxxMirror.cpp | 12 +- ReflectionTemplateLib/access/src/Function.cpp | 135 ++++++++---------- ReflectionTemplateLib/access/src/Instance.cpp | 5 +- ReflectionTemplateLib/access/src/RStatus.cpp | 27 ++-- ReflectionTemplateLib/access/src/Record.cpp | 6 +- .../detail/src/CxxReflection.cpp | 4 +- 11 files changed, 265 insertions(+), 202 deletions(-) diff --git a/ReflectionTemplateLib/access/inc/Function.h b/ReflectionTemplateLib/access/inc/Function.h index f29e0fdc..6309c737 100644 --- a/ReflectionTemplateLib/access/inc/Function.h +++ b/ReflectionTemplateLib/access/inc/Function.h @@ -10,61 +10,75 @@ namespace rtl { - namespace detail { - class CxxReflection; + namespace detail { + //forward decls + class CxxReflection; class ReflectionBuilder; } - namespace access + namespace access { - class Function - { - const TypeQ m_qualifier; - const std::size_t m_recordTypeId; + /* @class: Function, (callable object) + * every functor (function/method pointer), constructor, destructor registered will produce a 'Function' object + * it contains the meta-data of the functor along with 'FunctorId' to lookup for the same in functor-table. + * once the Function object is obtained, it can be called with the correct set of arguments, which will finally + perform call on the functor represented by this object. + */ class Function + { + //TypeQ::Const/Mute represents the const/non-const member-function, Type::None for non-member functions. + const TypeQ m_qualifier; - const std::string m_record; - const std::string m_function; - const std::string m_namespace; + //type id of class/struct (if it represents a member-function, else always '0') + const std::size_t m_recordTypeId; - mutable std::vector m_functorIds; + //name of the class/struct it belongs to, empty for non-member function. + const std::string m_record; - Function(); - Function(const std::string& pNamespace, const std::string& pClassName, const std::string& pFuncName, - const detail::FunctorId& pFunctorId, std::size_t pRecordTypeId, const TypeQ pQualifier); + //name of the function as supplied by the user. + const std::string m_function; - void addOverload(const Function& pOtherFunc) const; + //name of the namespace as supplied by the user. + const std::string m_namespace; - GETTER_REF(std::vector, FunctorIds, m_functorIds) + //FunctorId acts as a hash-key to look up the functor in table. multiple 'FunctoreId' for overloaded functors. + mutable std::vector m_functorIds; - protected: + Function(const std::string& pNamespace, const std::string& pClassName, + const std::string& pFuncName, const detail::FunctorId& pFunctorId, + const std::size_t pRecordTypeId, const TypeQ pQualifier); - Function(const Function& pOther, const detail::FunctorId& pFunctorId, - const std::string& pFunctorName); + void addOverload(const Function& pOtherFunc) const; - const std::size_t hasSignatureId(const std::size_t& pSignatureId) const; + GETTER_REF(std::vector, FunctorIds, m_functorIds) - public: + protected: - GETTER(TypeQ, Qualifier, m_qualifier) - GETTER(std::string, RecordName, m_record) - GETTER(std::string, Namespace, m_namespace) - GETTER(std::string, FunctionName, m_function) - GETTER(std::size_t, RecordTypeId, m_recordTypeId) - GETTER(std::vector, Functors, m_functorIds) + Function(const Function& pOther, const detail::FunctorId& pFunctorId, + const std::string& pFunctorName); - const std::string getHashCode() const; + const std::size_t hasSignatureId(const std::size_t& pSignatureId) const; - template - const bool hasSignature() const; + public: - template - RStatus operator()(_args...params) const noexcept; + //simple inlined getters. + GETTER(TypeQ, Qualifier, m_qualifier) + GETTER(std::string, RecordName, m_record) + GETTER(std::string, Namespace, m_namespace) + GETTER(std::string, FunctionName, m_function) + GETTER(std::size_t, RecordTypeId, m_recordTypeId) + GETTER(std::vector, Functors, m_functorIds) - template - RStatus call(_args...params) const noexcept; + template + const bool hasSignature() const; - friend detail::CxxReflection; - friend detail::ReflectionBuilder; - }; - } + template + RStatus operator()(_args...params) const noexcept; + + template + RStatus call(_args...params) const noexcept; + + friend detail::CxxReflection; + friend detail::ReflectionBuilder; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/Function.hpp b/ReflectionTemplateLib/access/inc/Function.hpp index 2dc44d6c..6874f1bd 100644 --- a/ReflectionTemplateLib/access/inc/Function.hpp +++ b/ReflectionTemplateLib/access/inc/Function.hpp @@ -7,42 +7,64 @@ namespace rtl { - namespace access - { - template + namespace access + { + /* @method: hasSignature<...>() + @param: set of arguments, explicitly specified as template parameter. + @return: bool, if the functor associated with this object is of certain signature or not. + * a single 'Function' object can be associated with multiple overloads of same function. + * the set of arguments passed is checked agains all registered overloads, returns true if matched with any one. + */ template inline const bool Function::hasSignature() const { + //hasSignatureId() returns the index of functor in functor table, which cannot be '-1'. return (hasSignatureId(detail::FunctorContainer<_arg0, _args...>::getContainerId()) != -1); } - template<> + /* @method: hasSignature() + @param: set of arguments, explicitly specified as template parameter. + @return: bool, if the functor associated with this object doesn't takes any argument. + */ template<> inline const bool Function::hasSignature() const { + //hasSignatureId() returns the index of functor in functor table, which cannot be '-1'. return (hasSignatureId(detail::FunctorContainer<>::getContainerId()) != -1); } - template + /* @method: operator()() + @param: variadic arguments. + @return: RStatus, containing the call status & return value of from the reflected call. + * if the arguments did not match with any overload, returns RStatus with Error::SignatureMismatch + * providing optional syntax, Function::call() does the exact same thing. + */ template inline RStatus Function::operator()(_args ...params) const noexcept { const std::size_t& index = hasSignatureId(detail::FunctorContainer<_args...>::getContainerId()); - if (index != -1) + if (index != -1) //true, if the arguments sent matches the functor signature associated with this 'Function' object { return detail::FunctorContainer<_args...>::forwardCall(index, params...); } + //else return with Error::SignatureMismatch. return RStatus(Error::SignatureMismatch); } - template + /* @method: call() + @param: variadic arguments. + @return: RStatus, containing the call status & return value of from the reflected call. + * if the arguments did not match with any overload, returns RStatus with Error::SignatureMismatch. + * providing optional syntax, Function::operator()() does the exact same thing. + */ template inline RStatus Function::call(_args ...params) const noexcept { const std::size_t& index = hasSignatureId(detail::FunctorContainer<_args...>::getContainerId()); - if (index != -1) + if (index != -1) //true, if the arguments sent matches the functor signature associated with this 'Function' object { return detail::FunctorContainer<_args...>::forwardCall(index, params...); } + //else return with Error::SignatureMismatch. return RStatus(Error::SignatureMismatch); } } diff --git a/ReflectionTemplateLib/access/inc/Instance.h b/ReflectionTemplateLib/access/inc/Instance.h index 0d8057f7..eed64651 100644 --- a/ReflectionTemplateLib/access/inc/Instance.h +++ b/ReflectionTemplateLib/access/inc/Instance.h @@ -20,7 +20,6 @@ namespace rtl { mutable TypeQ m_qualifier; const std::size_t m_typeId; - const std::size_t m_constTypeId; const std::any m_anyObject; const std::shared_ptr m_destructor; diff --git a/ReflectionTemplateLib/access/inc/RStatus.h b/ReflectionTemplateLib/access/inc/RStatus.h index 0017b585..ac4c5b71 100644 --- a/ReflectionTemplateLib/access/inc/RStatus.h +++ b/ReflectionTemplateLib/access/inc/RStatus.h @@ -6,38 +6,56 @@ namespace rtl { - namespace access - { - class RStatus - { - const Error m_callStatus; - const TypeQ m_typeQualifier; - - const std::any m_returnObj; - const std::size_t m_typeId; - - public: - - RStatus(const Error pCallStatus); - - RStatus(const std::any& pRetObj, const std::size_t pTypeId, const TypeQ pQualifier); - - GETTER(std::any, Return, m_returnObj) - GETTER(std::size_t, TypeId, m_typeId) - GETTER(TypeQ, Qualifier, m_typeQualifier) - - operator bool() const { - return (m_callStatus == Error::None); - } - - const bool operator==(const Error pError) const { - return (m_callStatus == pError); - } - - template - constexpr const bool isOfType() const { - return (detail::TypeId<_type>::get() == m_typeId); - } - }; - } + namespace access + { + /* @class: RStatus + * Every reflection call made, returns a RStatus object. + * it contains the error status of the call, defined by enum rtl::Error (in Constants.h) + * indicates all possible failure-errors that could happen on calling reflected funtion/method/constructor. + * it also contains the return value/object from the reflected function/method call wrapped under std::any. + */ class RStatus + { + //indicates the reflection call status error + const Error m_callStatus; + + //indicates whether the returned value from reflected call is const/non-const. + const TypeQ m_typeQualifier; + + //contains the return value of the from reflected call. Type erased. + const std::any m_returnObj; + + //type-id of the return value. + const std::size_t m_typeId; + + public: + + //used when the reflected call doesn't have any return value, or in case of call failure. + RStatus(const Error pCallStatus); + + //used when the reflected call returns a value, always in case of no call failure. + RStatus(const std::any& pRetObj, const std::size_t pTypeId, const TypeQ pQualifier); + + GETTER(std::any, Return, m_returnObj) + GETTER(std::size_t, TypeId, m_typeId) + GETTER(TypeQ, Qualifier, m_typeQualifier) + + //RStatus object converted to bool based on call succes or not. + operator bool() const { + //Error::None, reflected call successful. + return (m_callStatus == Error::None); + } + + //RStatus object can be directly checked agains any error-code. + const bool operator==(const Error pError) const { + return (m_callStatus == pError); + } + + //check if the returned object is of certain type. expected type must be passed as template param. + //if the expected type is 'const', must be used as templeate parameter. + template + constexpr const bool isOfType() const { + return (detail::TypeId<_type>::get() == m_typeId); + } + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/Record.hpp b/ReflectionTemplateLib/access/inc/Record.hpp index 60a20e74..109b9cdd 100644 --- a/ReflectionTemplateLib/access/inc/Record.hpp +++ b/ReflectionTemplateLib/access/inc/Record.hpp @@ -7,24 +7,47 @@ namespace rtl { - namespace access - { - template - inline const std::pair Record::instance(_ctorArgs ...params) const - { - const std::string& ctor = CtorName::ctor(m_recordName); - const auto& itr = m_methods.find(ctor); - if (itr != m_methods.end()) { - const RStatus& status = itr->second.invokeCtor(params...); - if (status) { - const std::string& dctor = CtorName::dctor(m_recordName); - return std::make_pair(status, Instance(status.getReturn(), status, *getMethod(dctor))); - } - return std::make_pair(status, Instance()); - } - else { - return std::make_pair(RStatus(Error::ConstructorNotFound), Instance()); - } - } - } + namespace access + { + /* @method: instance + @param: ...params (any number/type of arguments) + @return: std::pair + * calls the constructor of the calss/struct represented by this 'Record' object. + * returns the dynamically allocated object of the calss/struct along with the status. + * only default or any other overloaded constructor is called, except copy (for that check, Record::clone()). + * if the signature(...params) did not match any registered ctor, Error::SignatureMismatch is returned as RStatus. + * if no constructor found, Error::ConstructorNotFound is returned as RStatus. + * in case of reflected call failure, empty 'Instance' will be returned. + * on success Error::None will be returned along with the newly constructed object wrapped under 'Instance' (type erased). + */ template + inline const std::pair Record::instance(_ctorArgs ...params) const + { + const std::string& ctor = CtorName::ctor(m_recordName); + const auto& itr = m_methods.find(ctor); + + //if registered constructor is found for the class/struct represented by this 'Record' object. + if (itr != m_methods.end()) { + + //invoke the constructor, forwarding the arguments. + const RStatus& status = itr->second.invokeCtor(params...); + + //if status is 'true', object construction is successful. + if (status) { + + //get the destructor method, which is gauranteed to be present, if at least one constructor is registered. + const std::string& dctor = CtorName::dctor(m_recordName); + + //construct the 'Instance' object, assigning the destructor, its lifetime is managed via std::shared_ptr. + return std::make_pair(status, Instance(status.getReturn(), status, *getMethod(dctor))); + } + //if reflected call fails, return with empty 'Instance'. + return std::make_pair(status, Instance()); + } + else { + + //if no constructor found, return with empty 'Instance'. + return std::make_pair(RStatus(Error::ConstructorNotFound), Instance()); + } + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/src/CxxMirror.cpp b/ReflectionTemplateLib/access/src/CxxMirror.cpp index 499844bf..26d9db53 100644 --- a/ReflectionTemplateLib/access/src/CxxMirror.cpp +++ b/ReflectionTemplateLib/access/src/CxxMirror.cpp @@ -12,10 +12,10 @@ namespace rtl { /* @Constructor: CxxMirror @params: 'const std::vector&' * accepts vector of 'Function' objects, which are hash-key to lookup a functor. - * the only constructor to construct 'CxxMirror' object. - * Syntax for constructing - CxxMirror({ Reflect().function("func_name").build(), ..., ... }) - * '.build()' function will return a 'Function' object, and passed to std::vector initializer list. - * the vector is simply forwarded to the base class constructor. + * the only constructor to construct 'CxxMirror' object. + * Syntax for constructing - CxxMirror({ Reflect().function("func_name").build(), ..., ... }) + * '.build()' function will return a 'Function' object, and passed to std::vector initializer list. + * the vector is simply forwarded to the base class constructor. */ CxxMirror::CxxMirror(const std::vector& pFunctions) : detail::CxxReflection(pFunctions) { } @@ -26,7 +26,7 @@ namespace rtl { @return: std::optional * if the class/struct isn't found by the given name, std::nullopt is returned. * every class/struct's is grouped under a namespace. - * if no namespace is specified while registration, NAMESPACE_GLOBAL is used. + * if no namespace is specified while registration, NAMESPACE_GLOBAL is used. */ std::optional CxxMirror::getRecord(const std::string& pRecord) const { return getRecord(NAMESPACE_GLOBAL, pRecord); @@ -48,7 +48,7 @@ namespace rtl { /* @method: getRecord @param: std::string (namespace name), std::string (class/struct name) @return: std::optional - * retrieves the class/struct (as Record) registered under the given namespace. + * retrieves the class/struct (as Record) registered under the given namespace. * if the class/struct isn't found by the given name, std::nullopt is returned. */ std::optional CxxMirror::getRecord(const std::string& pNameSpace, const std::string& pRecord) const { diff --git a/ReflectionTemplateLib/access/src/Function.cpp b/ReflectionTemplateLib/access/src/Function.cpp index fae21ad8..56311e36 100644 --- a/ReflectionTemplateLib/access/src/Function.cpp +++ b/ReflectionTemplateLib/access/src/Function.cpp @@ -1,81 +1,68 @@ -#include -#include - #include "Function.h" namespace rtl { - namespace access - { - Function::Function() - : m_qualifier(TypeQ::None) - , m_recordTypeId(detail::TypeId<>::None) - , m_record("") - , m_function("") - , m_namespace("") + namespace access + { + Function::Function(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction, const detail::FunctorId& pFunctorId, + const std::size_t pRecordTypeId, const TypeQ pQualifier) + : m_qualifier(pQualifier) + , m_recordTypeId(pRecordTypeId) + , m_functorIds({ pFunctorId }) + , m_record(pRecord) + , m_function(pFunction) + , m_namespace(pNamespace) { + } + + + Function::Function(const Function& pOther, const detail::FunctorId& pFunctorId, + const std::string& pFunctorName) + : m_qualifier(pOther.m_qualifier) + , m_recordTypeId(pOther.m_recordTypeId) + , m_functorIds({ pFunctorId }) + , m_record(pOther.m_record) + , m_function(pFunctorName) + , m_namespace(pOther.m_namespace) { + } + + + /* @method: hasSignatureId() + @param: const std::size_t& (signatureId to be found) + @return: the index of the functor in the functor-table. + * a 'Function' object may be associated with multiple functors in case of overloads. + * every overload will have unique 'FunctorId', contained by one 'Function' object. + * given signatureId is compared against the signatureId of all overloads registered. + */ const std::size_t Function::hasSignatureId(const std::size_t& pSignatureId) const + { + //simple linear-search, most efficient for small set of elements. + for (const auto& functorId : m_functorIds) { + if (functorId.getSignatureId() == pSignatureId) { + return functorId.getIndex(); + } + } + return -1; + } + + + /* @method: addOverload() + @param: 'Function' object + * every 'Function' object produced while registration will have a single 'FunctorId' object, except constructors. + * for overloads registered with the same name, the 'FunctorId' from the other 'Function' object will be accumlated in one. + * if the same functor is registered again with the same name, it will be ignored. + */ void Function::addOverload(const Function& pOtherFunc) const { - } - - - Function::Function(const std::string& pNamespace, const std::string& pRecord, const std::string& pFunction, - const detail::FunctorId& pFunctorId, std::size_t pRecordTypeId, const TypeQ pQualifier) - : m_qualifier(pQualifier) - , m_recordTypeId(pRecordTypeId) - , m_functorIds({ pFunctorId }) - , m_record(pRecord) - , m_function(pFunction) - , m_namespace(pNamespace) { - } - - - Function::Function(const Function& pOther, const detail::FunctorId& pFunctorId, - const std::string& pFunctorName) - : m_qualifier(pOther.m_qualifier) - , m_recordTypeId(pOther.m_recordTypeId) - , m_functorIds({ pFunctorId }) - , m_record(pOther.m_record) - , m_function(pFunctorName) - , m_namespace(pOther.m_namespace) { - } - - - const std::string Function::getHashCode() const - { - std::string hashCode; - for (const auto& funcId : m_functorIds) { - hashCode += std::to_string(funcId.getHashCode()) + ", "; - } - hashCode.pop_back(); - hashCode.pop_back(); - return hashCode; - } - - - const std::size_t Function::hasSignatureId(const std::size_t& pSignatureId) const - { - const auto& itr = std::find_if(m_functorIds.begin(), m_functorIds.end(), - [pSignatureId](const detail::FunctorId& functorId) { - return (functorId.getSignatureId() == pSignatureId); - }); - return (itr == m_functorIds.end() ? -1 : itr->getIndex()); - } - - - void Function::addOverload(const Function& pOtherFunc) const - { - const std::size_t& otherFuncSignId = pOtherFunc.m_functorIds[0].getSignatureId(); - - auto itr = std::find_if(m_functorIds.begin(), m_functorIds.end(), - [otherFuncSignId](const detail::FunctorId& functorId) { - return (functorId.getSignatureId() == otherFuncSignId); - }); - - if (itr != m_functorIds.end()) { - assert(false && "multiple registration of same function"); - } - - m_functorIds.push_back(pOtherFunc.m_functorIds[0]); - } - } + const std::size_t& otherFuncSignId = pOtherFunc.m_functorIds[0].getSignatureId(); + //simple linear-search, most efficient for small set of elements. + for (const auto& functorId : m_functorIds) { + if (functorId.getSignatureId() == otherFuncSignId) { + return; //ignore and return if its already registered. + } + } + + //add the 'functorId' of the overloaded functor. + m_functorIds.push_back(pOtherFunc.m_functorIds[0]); + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/src/Instance.cpp b/ReflectionTemplateLib/access/src/Instance.cpp index 1a616450..c1d838a9 100644 --- a/ReflectionTemplateLib/access/src/Instance.cpp +++ b/ReflectionTemplateLib/access/src/Instance.cpp @@ -37,15 +37,13 @@ namespace rtl { Instance::Instance() : m_qualifier(TypeQ::None) - , m_typeId(detail::TypeId<>::None) - , m_constTypeId(detail::TypeId<>::None) { + , m_typeId(detail::TypeId<>::None) { } Instance::Instance(const Instance& pOther) : m_qualifier(pOther.m_qualifier) , m_typeId(pOther.m_typeId) - , m_constTypeId(pOther.m_constTypeId) , m_anyObject(pOther.m_anyObject) , m_destructor(pOther.m_destructor) { } @@ -54,7 +52,6 @@ namespace rtl { Instance::Instance(const std::any& pRetObj, const RStatus& pStatus, const Function& pDctor) : m_qualifier(TypeQ::Mute) , m_typeId(pStatus.getTypeId()) - , m_constTypeId(pStatus.getTypeId()) , m_anyObject(pRetObj) , m_destructor(&g_instanceCount, [=](void* ptr) { diff --git a/ReflectionTemplateLib/access/src/RStatus.cpp b/ReflectionTemplateLib/access/src/RStatus.cpp index 5fe472c2..06fd8988 100644 --- a/ReflectionTemplateLib/access/src/RStatus.cpp +++ b/ReflectionTemplateLib/access/src/RStatus.cpp @@ -3,20 +3,21 @@ namespace rtl { - namespace access { + namespace access { - RStatus::RStatus(const Error pCallStatus) - : m_callStatus(pCallStatus) - , m_typeQualifier(TypeQ::None) - , m_typeId(detail::TypeId<>::None) { - } + RStatus::RStatus(const Error pCallStatus) + : m_callStatus(pCallStatus) + , m_typeQualifier(TypeQ::None) + //no type is represented by value '0'. + , m_typeId(detail::TypeId<>::None) { + } - RStatus::RStatus(const std::any& pRetObj, const std::size_t pTypeId, const TypeQ pQualifier) - : m_callStatus(Error::None) - , m_typeQualifier(pQualifier) - , m_returnObj(pRetObj) - , m_typeId(pTypeId) { - } - } + RStatus::RStatus(const std::any& pRetObj, const std::size_t pTypeId, const TypeQ pQualifier) + : m_callStatus(Error::None) + , m_typeQualifier(pQualifier) + , m_returnObj(pRetObj) + , m_typeId(pTypeId) { + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/src/Record.cpp b/ReflectionTemplateLib/access/src/Record.cpp index f304a0ec..4df8986d 100644 --- a/ReflectionTemplateLib/access/src/Record.cpp +++ b/ReflectionTemplateLib/access/src/Record.cpp @@ -78,7 +78,7 @@ namespace rtl { { if (constCopyCtor) { - /* type of the object wrapped inder source 'Instance' should match with type of the class/struct + /* type of the object wrapped under source 'Instance' should match with type of the class/struct associated by constructor ('Function')object. */ if (constCopyCtor->getRecordTypeId() != pOther.getTypeId()) { //if source instance & ctor type didn't match, return empty instance with error status. @@ -98,7 +98,7 @@ namespace rtl { std::optional copyCtor = getMethod(copyStr); if (copyCtor) { - /* type of the object wrapped inder source 'Instance' should match with type of the class/struct + /* type of the object wrapped under source 'Instance' should match with type of the class/struct associated by constructor ('Function')object. */ if (copyCtor->getRecordTypeId() != pOther.getTypeId()) { //if source instance & ctor type didn't match, return empty instance with error status. @@ -111,7 +111,7 @@ namespace rtl { //if copy-constructor taking non-const ref not found, and with const-ref found, use that copy constructor. else if (constCopyCtor) { - /* type of the object wrapped inder source 'Instance' should match with type of the class/struct + /* type of the object wrapped under source 'Instance' should match with type of the class/struct associated by constructor ('Function')object. */ if (constCopyCtor->getRecordTypeId() != pOther.getTypeId()) { //if source instance & ctor type didn't match, return empty instance with error status. diff --git a/ReflectionTemplateLib/detail/src/CxxReflection.cpp b/ReflectionTemplateLib/detail/src/CxxReflection.cpp index 166ef8b5..4304845e 100644 --- a/ReflectionTemplateLib/detail/src/CxxReflection.cpp +++ b/ReflectionTemplateLib/detail/src/CxxReflection.cpp @@ -11,7 +11,7 @@ namespace rtl { /* @Constructor: CxxMirror @params: 'const std::vector&' * recieves vector of 'Function' objects, forwarded from 'CxxMirror' constructor. - * initiates grouping of each 'Function' object under namespace, class/struct. + * initiates grouping of each 'Function' object under namespace, class/struct. */ CxxReflection::CxxReflection(const std::vector& pFunctions) { for (const auto& function : pFunctions) { @@ -100,6 +100,7 @@ namespace rtl { { const auto& nameSpace = pFunction.getNamespace(); + //if the record-name is empty, 'Function' object is considered as non-member function. if (pFunction.getRecordName().empty()) { const auto& itr = m_nsFunctionsMap.find(nameSpace); if (itr == m_nsFunctionsMap.end()) { @@ -110,6 +111,7 @@ namespace rtl { addFunction(itr->second, pFunction); } } + //if the record-name is not-empty, 'Function' object is considered as member function, a 'Method'. else { const auto& itr = m_nsRecordsMap.find(nameSpace); if (itr == m_nsRecordsMap.end()) { From 7da7009106d8391dc0c6550b75541d9df21d2125 Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Mon, 22 Jul 2024 19:24:59 +0530 Subject: [PATCH 8/9] comments added. --- CxxReflectionTests/src/ClassMethodsTests.cpp | 12 +- .../src/ConstMethodOverloadTests.cpp | 12 +- CxxReflectionTests/src/ConstructorTests.cpp | 18 +- .../src/CopyConstructorTests.cpp | 10 +- .../src/NameSpaceGlobalsTests.cpp | 12 +- .../src/ReflectedCallStatusErrTests.cpp | 10 +- CxxReflectionTests/src/StaticMethodTests.cpp | 25 +- ReflectionTemplateLib/access/inc/Instance.h | 72 +++-- ReflectionTemplateLib/access/inc/Method.h | 267 ++++++++++------ ReflectionTemplateLib/access/inc/Method.hpp | 300 ++++++++++-------- ReflectionTemplateLib/access/src/Function.cpp | 28 +- ReflectionTemplateLib/access/src/Instance.cpp | 133 +++++--- ReflectionTemplateLib/detail/inc/FunctorId.h | 90 +++--- .../detail/src/CxxReflection.cpp | 8 +- .../detail/src/FunctorId.cpp | 30 +- 15 files changed, 626 insertions(+), 401 deletions(-) diff --git a/CxxReflectionTests/src/ClassMethodsTests.cpp b/CxxReflectionTests/src/ClassMethodsTests.cpp index bb73abab..adf38aad 100644 --- a/CxxReflectionTests/src/ClassMethodsTests.cpp +++ b/CxxReflectionTests/src/ClassMethodsTests.cpp @@ -24,7 +24,6 @@ namespace rtl_tests TEST(ReflectionMethodCall, wrong_args) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -47,12 +46,12 @@ namespace rtl_tests EXPECT_FALSE(book::test_method_setAuthor(bookObj.get())); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ClassBookMethod, args_void) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -78,12 +77,12 @@ namespace rtl_tests EXPECT_TRUE(book::test_method_getPublishedOn_return(retStr)); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ClassBookMethod, args_string) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -107,12 +106,12 @@ namespace rtl_tests EXPECT_TRUE(book::test_method_setAuthor(bookObj.get())); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ClassBookMethodOverload, args_void) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -135,12 +134,12 @@ namespace rtl_tests EXPECT_TRUE(book::test_method_updateBookInfo(bookObj.get())); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ClassBookMethodOverload, args_string_double_charPtr) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -165,12 +164,12 @@ namespace rtl_tests EXPECT_TRUE(isSuccess); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ClassBookMethodOverload, args_charPtr_double_string) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -195,5 +194,6 @@ namespace rtl_tests EXPECT_TRUE(isSuccess); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } } \ No newline at end of file diff --git a/CxxReflectionTests/src/ConstMethodOverloadTests.cpp b/CxxReflectionTests/src/ConstMethodOverloadTests.cpp index 65e2f0f3..a3560b46 100644 --- a/CxxReflectionTests/src/ConstMethodOverloadTests.cpp +++ b/CxxReflectionTests/src/ConstMethodOverloadTests.cpp @@ -11,7 +11,6 @@ namespace rtl_tests { TEST(ConstMethodOverload, const_method_no_overload_call_on_non_const_target) { - EXPECT_TRUE(person::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -35,12 +34,12 @@ namespace rtl_tests EXPECT_TRUE(person::test_method_updateLastName(personObj.get())); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ConstMethodOverload, const_method_no_overload_call_on_const_target) { - EXPECT_TRUE(person::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -66,12 +65,12 @@ namespace rtl_tests EXPECT_TRUE(person::test_method_updateLastName_const(personObj.get())); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ConstMethodOverload, const_method_string_call_on_const_target) { - EXPECT_TRUE(person::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -97,12 +96,12 @@ namespace rtl_tests EXPECT_TRUE(person::test_method_updateAddress_const(personObj.get())); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ConstMethodOverload, const_method_string_call_on_non_const_target) { - EXPECT_TRUE(person::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -125,12 +124,12 @@ namespace rtl_tests EXPECT_TRUE(person::test_method_updateAddress(personObj.get())); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ConstMethodOverload, const_method_no_args_call_on_const_target) { - EXPECT_TRUE(person::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -157,12 +156,12 @@ namespace rtl_tests EXPECT_TRUE(person::test_method_updateAddress_const(personObj.get())); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ConstMethodOverload, const_method_no_args_call_on_non_const_target) { - EXPECT_TRUE(person::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -186,5 +185,6 @@ namespace rtl_tests EXPECT_TRUE(person::test_method_updateAddress(personObj.get())); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } } \ No newline at end of file diff --git a/CxxReflectionTests/src/ConstructorTests.cpp b/CxxReflectionTests/src/ConstructorTests.cpp index 315b5594..e4210a32 100644 --- a/CxxReflectionTests/src/ConstructorTests.cpp +++ b/CxxReflectionTests/src/ConstructorTests.cpp @@ -25,7 +25,6 @@ namespace rtl_tests TEST(DynamicAllocConstructorDate, wrong_args) { - EXPECT_TRUE(date::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -38,12 +37,12 @@ namespace rtl_tests ASSERT_TRUE(instance.isEmpty()); } EXPECT_TRUE(date::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DynamicAllocConstructorDate, args_void) { - EXPECT_TRUE(date::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -57,12 +56,12 @@ namespace rtl_tests EXPECT_TRUE(date::test_dynamic_alloc_instance_ctor<>(instance.get())); } EXPECT_TRUE(date::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DynamicAllocConstructorDate, args_string) { - EXPECT_TRUE(date::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -77,12 +76,12 @@ namespace rtl_tests EXPECT_TRUE(date::test_dynamic_alloc_instance_ctor(instance.get())); } EXPECT_TRUE(date::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DynamicAllocConstructorDate, args_unsigned_unsigned_unsigned) { - EXPECT_TRUE(date::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -98,12 +97,12 @@ namespace rtl_tests EXPECT_TRUE(isPassed); } EXPECT_TRUE(date::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DestructorDate, non_virtual) { - EXPECT_TRUE(date::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -117,12 +116,12 @@ namespace rtl_tests EXPECT_TRUE(date::test_dynamic_alloc_instance_ctor<>(instance.get())); } EXPECT_TRUE(date::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DynamicAllocConstructorBook, wrong_args) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -135,12 +134,12 @@ namespace rtl_tests ASSERT_TRUE(instance.isEmpty()); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DynamicAllocConstructorBook, args_default) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -154,12 +153,12 @@ namespace rtl_tests EXPECT_TRUE(book::test_dynamic_alloc_instance_ctor(instance.get())); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DynamicAllocConstructorBook, args_double_string) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -177,12 +176,12 @@ namespace rtl_tests EXPECT_TRUE(isPassed); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(DestructorBook, non_virtual) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -196,5 +195,6 @@ namespace rtl_tests EXPECT_TRUE(book::test_dynamic_alloc_instance_ctor(instance.get())); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } } \ No newline at end of file diff --git a/CxxReflectionTests/src/CopyConstructorTests.cpp b/CxxReflectionTests/src/CopyConstructorTests.cpp index f9da35e3..9f867a04 100644 --- a/CxxReflectionTests/src/CopyConstructorTests.cpp +++ b/CxxReflectionTests/src/CopyConstructorTests.cpp @@ -14,7 +14,6 @@ namespace rtl_tests TEST(CopyConstructor, call_copy_ctor_of_PERSON_with_BOOK_instance) { - EXPECT_TRUE(book::assert_zero_instance_count()); { optional classPerson = MyReflection::instance().getRecord(person::class_); ASSERT_TRUE(classPerson); @@ -31,12 +30,12 @@ namespace rtl_tests ASSERT_TRUE(retStatus == Error::InstanceTypeMismatch); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(CopyConstructor, copy_ctor_arg_const_ref___src_instance_non_const) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -69,12 +68,12 @@ namespace rtl_tests EXPECT_TRUE(isPassed); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(CopyConstructor, copy_ctor_arg_const_ref___src_instance_const) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -110,12 +109,12 @@ namespace rtl_tests EXPECT_TRUE(isPassed); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(CopyConstructor, copy_ctor_arg_const_ref_overload___src_instance_const) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -136,12 +135,12 @@ namespace rtl_tests EXPECT_TRUE(isPassed); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(CopyConstructor, copy_ctor_arg_non_const_ref_overload___src_instance_non_const) { - EXPECT_TRUE(book::assert_zero_instance_count()); { CxxMirror& cxxMirror = MyReflection::instance(); @@ -160,5 +159,6 @@ namespace rtl_tests EXPECT_TRUE(isPassed); } EXPECT_TRUE(book::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } } \ No newline at end of file diff --git a/CxxReflectionTests/src/NameSpaceGlobalsTests.cpp b/CxxReflectionTests/src/NameSpaceGlobalsTests.cpp index 552b2c2b..05019476 100644 --- a/CxxReflectionTests/src/NameSpaceGlobalsTests.cpp +++ b/CxxReflectionTests/src/NameSpaceGlobalsTests.cpp @@ -17,12 +17,10 @@ namespace rtl_tests { optional badFunc = cxxMirror.getFunction("wrong_namespace", "wrong_function"); EXPECT_FALSE(badFunc); - } - { + } { optional badFunc = cxxMirror.getFunction(str_complex, "wrong_function"); EXPECT_FALSE(badFunc); - } - { + } { optional badFunc = cxxMirror.getFunction("wrong_getComplexNumAsString"); EXPECT_FALSE(badFunc); } @@ -130,8 +128,7 @@ namespace rtl_tests string retVal = std::any_cast(status.getReturn()); EXPECT_TRUE(retVal == STRA_REVERSE); - } - { + } { RStatus status = reverseString->call(string(STRB)); ASSERT_TRUE(status); ASSERT_TRUE(status.getReturn().has_value()); @@ -139,8 +136,7 @@ namespace rtl_tests string retVal = std::any_cast(status.getReturn()); EXPECT_TRUE(retVal == STRB_REVERSE); - } - { + } { RStatus status = (*reverseString)(); ASSERT_TRUE(status); ASSERT_TRUE(status.getReturn().has_value()); diff --git a/CxxReflectionTests/src/ReflectedCallStatusErrTests.cpp b/CxxReflectionTests/src/ReflectedCallStatusErrTests.cpp index 49e66276..0b72ef1d 100644 --- a/CxxReflectionTests/src/ReflectedCallStatusErrTests.cpp +++ b/CxxReflectionTests/src/ReflectedCallStatusErrTests.cpp @@ -27,7 +27,6 @@ namespace rtl_tests TEST(ReflectedCallStatusError, unregistered_constructor___error_CopyConstructorNotFound) { - EXPECT_TRUE(calender::assert_zero_instance_count()); { optional classCalender = MyReflection::instance().getRecord(calender::ns, calender::struct_); ASSERT_TRUE(classCalender); @@ -42,6 +41,7 @@ namespace rtl_tests ASSERT_TRUE(instance.isEmpty()); } EXPECT_TRUE(calender::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } @@ -76,6 +76,7 @@ namespace rtl_tests auto [retStatus, personObj] = classPerson->clone(emptyObj); ASSERT_TRUE(retStatus == Error::EmptyInstance); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } @@ -94,12 +95,12 @@ namespace rtl_tests RStatus retStatus = classBook->getMethod(book::str_getPublishedOn)->on(emptyObj).call(); ASSERT_TRUE(retStatus == Error::EmptyInstance); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ReflectedCallStatusError, unregistered_constructor___error_ConstCopyConstructorNotFound) { - EXPECT_TRUE(date::assert_zero_instance_count()); { optional classDate = MyReflection::instance().getRecord(date::ns, date::struct_); ASSERT_TRUE(classDate); @@ -116,12 +117,12 @@ namespace rtl_tests ASSERT_TRUE(instance.isEmpty()); } EXPECT_TRUE(date::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ReflectedCallStatusError, method_on_wrong_instance___error_InstanceTypeMismatch) { - EXPECT_TRUE(person::assert_zero_instance_count()); { optional classPerson = MyReflection::instance().getRecord(person::class_); ASSERT_TRUE(classPerson); @@ -140,12 +141,12 @@ namespace rtl_tests ASSERT_TRUE(retStatus == Error::InstanceTypeMismatch); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } TEST(ReflectedCallStatusError, non_const_method_on_const_Instance__error_InstanceConstMismatch) { - EXPECT_TRUE(person::assert_zero_instance_count()); { optional classBook = MyReflection::instance().getRecord(book::class_); ASSERT_TRUE(classBook); @@ -163,5 +164,6 @@ namespace rtl_tests ASSERT_TRUE(retStatus == Error::InstanceConstMismatch); } EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); } } \ No newline at end of file diff --git a/CxxReflectionTests/src/StaticMethodTests.cpp b/CxxReflectionTests/src/StaticMethodTests.cpp index ad17427f..083b0115 100644 --- a/CxxReflectionTests/src/StaticMethodTests.cpp +++ b/CxxReflectionTests/src/StaticMethodTests.cpp @@ -70,8 +70,7 @@ namespace rtl_tests const string& retStr = any_cast(status.getReturn()); EXPECT_EQ(retStr, person::get_str_returned_on_call_getProfile(true)); - } - { + } { //different syntax of calling. const RStatus& status = getProfile->on().call(false); @@ -111,4 +110,26 @@ namespace rtl_tests EXPECT_EQ(retStr, checkStr); } + + + TEST(StaticMethods, static_method_call_on_target_instance) + { + CxxMirror& cxxMirror = MyReflection::instance(); + + optional classPerson = cxxMirror.getRecord(person::class_); + ASSERT_TRUE(classPerson); + + optional getDefaults = classPerson->getMethod(person::str_getDefaults); + ASSERT_TRUE(getDefaults); + ASSERT_TRUE(getDefaults->hasSignature()); + + auto [isSuccess, personObj] = classPerson->instance(); + + ASSERT_TRUE(isSuccess); + ASSERT_FALSE(personObj.isEmpty()); + + //TODO: handle this test case with appropriate error or make successful call as its valid to call static method on objects. + const RStatus& status = (*getDefaults)(personObj)(); + ASSERT_TRUE(status == rtl::Error::InstanceTypeMismatch); + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/Instance.h b/ReflectionTemplateLib/access/inc/Instance.h index eed64651..387b4a6a 100644 --- a/ReflectionTemplateLib/access/inc/Instance.h +++ b/ReflectionTemplateLib/access/inc/Instance.h @@ -9,40 +9,62 @@ namespace rtl { - namespace access - { - class Record; - class RStatus; - class Function; + namespace access + { + //forward decls + class Record; + class RStatus; + class Function; - class Instance - { - mutable TypeQ m_qualifier; + /* @class: Instance + * type erased wrapper for objects created on heap via reflection. + * 'Instance' objects are only returned from Record::clone() & Recoed::instance() + * empty 'Instance' is returned if constructor is not found or if called with wrong args. + * 'Instance' objects are never created on heap, only the underlying object is created on heap. + * the lifetime of the underlying object is managed by std::shared_ptr. + */ class Instance + { + //indicates if object const/non-const. + mutable TypeQ m_qualifier; - const std::size_t m_typeId; + //type id of the containd object. + const std::size_t m_typeId; - const std::any m_anyObject; - const std::shared_ptr m_destructor; + //allocated object, stored without type info. + const std::any m_anyObject; - explicit Instance(); - explicit Instance(const std::any& pRetObj, const RStatus& pStatus, const Function& pDctor); + /* shared_ptr, wil be shared between the copies of the 'Instance'. + does not holds the objcet constructed via reflection. + it only contains a custom deleter to be called on the underlying object. + */ const std::shared_ptr m_destructor; - public: + //private constructors, only class 'Record' can access. + explicit Instance(); + explicit Instance(const std::any& pRetObj, const RStatus& pStatus, const Function& pDctor); - Instance(const Instance&); + public: - GETTER(std::any, , m_anyObject); - GETTER(std::size_t, TypeId, m_typeId); - GETTER(TypeQ, Qualifier, m_qualifier); + //creating copies is allowed. + Instance(const Instance&); - const bool isEmpty() const; - const bool isConst() const; + //simple inlined getters. + GETTER(std::any, , m_anyObject); + GETTER(std::size_t, TypeId, m_typeId); + GETTER(TypeQ, Qualifier, m_qualifier); - void makeConst(const bool& pCastAway = false); + //checks if it contains object constructed via reflection. + const bool isEmpty() const; - static std::size_t getInstanceCount(); + //check the contained object is const or not. + const bool isConst() const; - friend Record; - }; - } + //treat the object constructed via reflection as const or non-const. + void makeConst(const bool& pCastAway = false); + + //get the current number of objects constructed via reflection. + static std::size_t getInstanceCount(); + + friend Record; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/Method.h b/ReflectionTemplateLib/access/inc/Method.h index 676e83fc..60a99543 100644 --- a/ReflectionTemplateLib/access/inc/Method.h +++ b/ReflectionTemplateLib/access/inc/Method.h @@ -7,110 +7,167 @@ namespace rtl { - namespace access - { - class Method; - class Record; - - template - class MethodInvoker - { - const Method& m_method; - const Instance& m_target; + namespace access + { + //forward decls + class Method; + class Record; + + /* @class: MethodInvoker + @param: , can be any 'FunctorType' other than FunctorType::Static. + * invokes the assigned method on the assigned object. + * invokes only non-static member function via reflection. + * its objects are only cretaed and returned by 'Method::on()' method. + * purpose of this class is only to provide method call syntax like, 'method.on(target).call(params...)' + */ template + class MethodInvoker + { + //the method to be called. + const Method& m_method; + + //the object on which, the method needs to be called. + const Instance& m_target; - MethodInvoker(const Method& pMethod, const Instance& pTarget); - - public: - - template - RStatus call(_args...) const noexcept; - - friend Method; - }; - - - template<> - class MethodInvoker - { - const Method& m_method; - - MethodInvoker(const Method& pMethod); - - public: - - template - RStatus call(_args...) const noexcept; - - friend Method; - }; - - - class Method : public Function - { - Method(const Function& pFunction); - - Method(const Function& pFunction, const detail::FunctorId& pFunctorId, const std::string& pFunctorName); - - template - RStatus invokeCtor(_args...params) const; - - template - RStatus invoke(const Instance& pTarget, _args...params) const; - - template - RStatus invokeConst(const Instance& pTarget, _args...params) const; - - template - RStatus invokeStatic(_args...params) const; - - static Method getDestructorMethod(const Function& pFunction, const detail::FunctorId& pFunctorId); - - public: - - template - const bool hasSignature() const; - - const MethodInvoker on() const; - const MethodInvoker on(const Instance& pTarget) const; - - constexpr auto operator()() const - { - return [this](auto...params) { - return Function::operator()(params...); - }; - } - - constexpr auto operator()(const Instance& pTarget) const - { - return [&](auto...params)->RStatus - { - if (pTarget.isEmpty()) { - return RStatus(Error::EmptyInstance); - } - - if (pTarget.getTypeId() != getRecordTypeId()) { - return RStatus(Error::InstanceTypeMismatch); - } - - switch (pTarget.getQualifier()) - { - case TypeQ::Mute: return invoke(pTarget, params...); - case TypeQ::Const: return invokeConst(pTarget, params...); - } - return RStatus(Error::EmptyInstance); - }; - } - - template - RStatus operator()(_args...) const noexcept = delete; - - template - RStatus call(_args...) const noexcept = delete; - - template - friend class MethodInvoker; - friend detail::CxxReflection; - friend Record; - }; - } + MethodInvoker(const Method& pMethod, const Instance& pTarget); + + public: + + template + RStatus call(_args...) const noexcept; + + friend Method; + }; + + + /* @class: MethodInvoker + @param: FunctorType::Static (explicitly specialized) + * invokes the assigned method on the assigned object. + * invokes only static member function via reflection. + * its objects are only cretaed and returned by 'Method::on()' method. + * purpose of this class is only to provide method call syntax like, 'method.on().call(params...)' + * 'on()' will take no target as parameter, since the method being called is 'static'. + */ template<> + class MethodInvoker + { + const Method& m_method; + + MethodInvoker(const Method& pMethod); + + public: + + template + RStatus call(_args...) const noexcept; + + friend Method; + }; + + + /* @class: Method + * extends 'Function' class and adds interfaces to call member function. + * invokes only static & non-static member functions via reflection. + * deletes the base's 'operator()()'. + * redefines 'operator()()', to accept only target object and returns lambda. + * the returned lambda is then called with the arguments corresponding to the functor associated with it. + */ class Method : public Function + { + //private ctor, called by 'Record' class. + Method(const Function& pFunction); + + //private ctor, called by 'Record' class. + Method(const Function& pFunction, const detail::FunctorId& pFunctorId, const std::string& pFunctorName); + + //invokes the constructor associated with this 'Method' + template + RStatus invokeCtor(_args...params) const; + + //invokes the member-function associated with this 'Method' + template + RStatus invoke(const Instance& pTarget, _args...params) const; + + //invokes only const member-function associated with this 'Method' + template + RStatus invokeConst(const Instance& pTarget, _args...params) const; + + //invokes only static member-function associated with this 'Method' + template + RStatus invokeStatic(_args...params) const; + + //called from class 'Record', creates a 'Method' object for destructor. + static Method getDestructorMethod(const Function& pFunction, const detail::FunctorId& pFunctorId); + + public: + + //indicates if a particular set of arguments accepted by the functor associated with it. + template + const bool hasSignature() const; + + //set 'no' object to call static method. (takes no parameter) + const MethodInvoker on() const; + + //set 'target' object on which the functor associated with this will be called. + const MethodInvoker on(const Instance& pTarget) const; + + + /* @method: operator()() + @return: lambda + * accepts no arguments for 'target', since associated functor is static-member-functions. + * returns a lambda, which forwards the call to finally call the associated static-member-function functor. + * provides syntax like,'method()(params...)', first'()' is empty & second'()' takes the actual params. + */ constexpr auto operator()() const + { + return [this](auto...params) { + return Function::operator()(params...); + }; + } + + + /* @method: operator()(const Instance&) + @param: const Instance& (target object) + @return: lambda + * accepts 'pTarget', which contains the actual object on which the member-function functor associated with 'this' is invoked. + * returns a lambda, which forwards the call to finally call the associated non-static-member-function functor. + * provides syntax like, 'method(pTarget)(params...)', keeping the target & params seperate. + */ constexpr auto operator()(const Instance& pTarget) const + { + return [&](auto...params)->RStatus + { + if (pTarget.isEmpty()) { + //if the target is empty. + return RStatus(Error::EmptyInstance); + } + + if (pTarget.getTypeId() != getRecordTypeId()) { + //if the target type-id & type-id of the 'class/struct' owner of the associated functor do not match. + return RStatus(Error::InstanceTypeMismatch); + } + + switch (pTarget.getQualifier()) + { + //if the target is non-const, const & non-const member function can be invoked on it. + case TypeQ::Mute: return invoke(pTarget, params...); + + //if the target is const, only const member function can be invoked on it. + case TypeQ::Const: return invokeConst(pTarget, params...); + } + + //only an empty 'Instance' will have TypeQ::None. + return RStatus(Error::EmptyInstance); + }; + } + + //deletes base class 'operator()()' + template + RStatus operator()(_args...) const noexcept = delete; + + //deletes base class 'call()' + template + RStatus call(_args...) const noexcept = delete; + + //friends :) + template + friend class MethodInvoker; + friend detail::CxxReflection; + friend Record; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/Method.hpp b/ReflectionTemplateLib/access/inc/Method.hpp index 4c1943fd..3c953477 100644 --- a/ReflectionTemplateLib/access/inc/Method.hpp +++ b/ReflectionTemplateLib/access/inc/Method.hpp @@ -3,133 +3,179 @@ namespace rtl { - namespace access + namespace access { - template - inline MethodInvoker<_type>::MethodInvoker(const Method& pMethod, const Instance& pTarget) - : m_method(pMethod) - , m_target(pTarget) { - } - - - template - template - inline RStatus MethodInvoker<_type>::call(_args ...params) const noexcept - { - if (m_target.isEmpty()) { - return RStatus(Error::EmptyInstance); - } - - if (m_target.getTypeId() != m_method.getRecordTypeId()) { - return RStatus(Error::InstanceTypeMismatch); - } - - switch (m_target.getQualifier()) - { - case TypeQ::Mute: return m_method.invoke(m_target, params...); - case TypeQ::Const: return m_method.invokeConst(m_target, params...); - } - return RStatus(Error::EmptyInstance); - } - - - inline MethodInvoker::MethodInvoker(const Method& pMethod) - :m_method(pMethod) { - } - - - template - inline RStatus MethodInvoker::call(_args ...params) const noexcept - { - return m_method.invokeStatic(params...); - } - } - - - namespace access + //MethodInvoker, holds const-ref of the 'Method' and 'Instance' on which it will be invoked. + template + inline MethodInvoker<_type>::MethodInvoker(const Method& pMethod, const Instance& pTarget) + : m_method(pMethod) + , m_target(pTarget) { + } + + + /* @method: call() + @params: params... (corresponding to functor associated with 'm_method') + @return: RStatus, indicating success of the reflected call. + * invokes non-static-member-function functor associated with 'm_method' on object 'm_target'. + */ template + template + inline RStatus MethodInvoker<_type>::call(_args ...params) const noexcept + { + if (m_target.isEmpty()) { + //if the target is empty. + return RStatus(Error::EmptyInstance); + } + + if (m_target.getTypeId() != m_method.getRecordTypeId()) { + //if the m_target's type-id & type-id of the 'class/struct' owner of the associated functor(m_method's) do not match. + return RStatus(Error::InstanceTypeMismatch); + } + + switch (m_target.getQualifier()) + { + //if the target is non-const, const & non-const both type member-function can be invoked on it. + case TypeQ::Mute: return m_method.invoke(m_target, params...); + + //if the m_target is const, only const member function can be invoked on it. + case TypeQ::Const: return m_method.invokeConst(m_target, params...); + } + + //only an empty 'Instance' will have TypeQ::None. + return RStatus(Error::EmptyInstance); + } + + //MethodInvoker, holds only 'Method' associated with a static-member-function. + inline MethodInvoker::MethodInvoker(const Method& pMethod) + :m_method(pMethod) { + } + + + template + inline RStatus MethodInvoker::call(_args ...params) const noexcept + { + //invokes the static-member-function functor associated with 'm_method'. no need of 'm_target' as other 'MethodInvoker'. + return m_method.invokeStatic(params...); + } + } + + + namespace access { - inline const MethodInvoker Method::on() const - { - return MethodInvoker(*this); - } - - - inline const MethodInvoker Method::on(const Instance& pTarget) const - { - return MethodInvoker(*this, pTarget); - } - - - template - inline RStatus Method::invokeCtor(_args ...params) const - { - return Function::operator()(params...); - } - - - template - inline RStatus Method::invokeStatic(_args ...params) const - { - return Function::operator()(params...); - } - - - template<> - inline const bool Method::hasSignature() const - { - switch (getQualifier()) - { - case TypeQ::None: return Function::hasSignature(); - case TypeQ::Mute: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); - case TypeQ::Const: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); - } - return false; - } - - - template - inline const bool Method::hasSignature() const - { - switch (getQualifier()) - { - case TypeQ::None: return Function::hasSignature<_arg0, _args...>(); - case TypeQ::Mute: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); - case TypeQ::Const: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); - } - return false; - } - - - template - inline RStatus Method::invokeConst(const Instance& pTarget, _args ...params) const - { - const std::size_t& index = hasSignatureId(detail::MethodContainer::getContainerId()); - if (index != -1) - { - return detail::MethodContainer::forwardCall(pTarget.get(), index, params...); - } - else { - const std::size_t& index = hasSignatureId(detail::MethodContainer::getContainerId()); - if (index != -1) { - return RStatus(Error::InstanceConstMismatch); - } - } - return RStatus(Error::SignatureMismatch); - } - - - template - inline RStatus Method::invoke(const Instance& pTarget, _args ...params) const - { - const std::size_t& index = hasSignatureId(detail::MethodContainer::getContainerId()); - if (index != -1) - { - return detail::MethodContainer::forwardCall(pTarget.get(), index, params...); - } - else { - return invokeConst(pTarget, params...); - } - return RStatus(Error::SignatureMismatch); - } - } + /* @method: on() + @return: MethodInvoker + * accepts no arguments for 'target', since associated functor is static-member-functions. + */ inline const MethodInvoker Method::on() const + { + return MethodInvoker(*this); + } + + + inline const MethodInvoker Method::on(const Instance& pTarget) const + { + return MethodInvoker(*this, pTarget); + } + + + /* @method: invokeCtor() + @params: variable arguments. + @return: RStatus + * calls the constructor with given arguments. + */ template + inline RStatus Method::invokeCtor(_args ...params) const + { + return Function::operator()(params...); + } + + + /* @method: invokeStatic() + @params: variable arguments. + @return: RStatus + * with given arguments, calls the static-member-function functor associated with this 'Method'. + */ template + inline RStatus Method::invokeStatic(_args ...params) const + { + return Function::operator()(params...); + } + + + /* @method: hasSignature() + @return: bool + * checks if the member-function functor associated with this 'Method', takes zero arguments or not. + */ template<> + inline const bool Method::hasSignature() const + { + switch (getQualifier()) + { + case TypeQ::None: return Function::hasSignature(); + case TypeQ::Mute: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); + case TypeQ::Const: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); + } + return false; + } + + + /* @method: hasSignature<...>() + @params: template params, <_arg0, ..._args> (expects at least one args- _args0) + @return: bool + * checks if the member-function functor associated with this 'Method', takes template specified arguments set or not. + */ template + inline const bool Method::hasSignature() const + { + switch (getQualifier()) + { + case TypeQ::None: return Function::hasSignature<_arg0, _args...>(); + case TypeQ::Mute: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); + case TypeQ::Const: return (hasSignatureId(detail::MethodContainer::getContainerId()) != -1); + } + return false; + } + + + /* @method: invokeConst() + @params: 'pTarget' (on which the method to be invoked), 'params...' (method arguments) + @return: 'RStatus', indicating the success of reflected method call. + * invokes only a const-member-function functor. + */ template + inline RStatus Method::invokeConst(const Instance& pTarget, _args ...params) const + { + //if the given argument's associated MethodContainer contains such member-functor, then make the call. + const std::size_t& index = hasSignatureId(detail::MethodContainer::getContainerId()); + if (index != -1) + { + //make the call. + return detail::MethodContainer::forwardCall(pTarget.get(), index, params...); + } + else { + //if the associated MethodContainer contains no such member-functor, check if such functor is present in container holding non-const functors. + const std::size_t& index = hasSignatureId(detail::MethodContainer::getContainerId()); + if (index != -1) { + //if yes, then return error indicating such 'functor' is present but can be called on only non-const 'Instance'. + return RStatus(Error::InstanceConstMismatch); + } + } + //return this error if the given argument's associated MethodContainer not found (const/non-const both). + return RStatus(Error::SignatureMismatch); + } + + + /* @method: invokeConst() + @params: 'pTarget' (on which the method to be invoked), 'params...' (method arguments) + @return: 'RStatus', indicating the success of reflected method call. + * can invoke a 'const' or non-const-member-function functor. + */ template + inline RStatus Method::invoke(const Instance& pTarget, _args ...params) const + { + //if the given argument's associated MethodContainer contains such member-functor, then make the call. + const std::size_t& index = hasSignatureId(detail::MethodContainer::getContainerId()); + if (index != -1) + { + //make the call. + return detail::MethodContainer::forwardCall(pTarget.get(), index, params...); + } + else { + //if no such member-functor is found in non-const MethodContainer, check if such functor is present in const MethodContainer. + return invokeConst(pTarget, params...); + } + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/src/Function.cpp b/ReflectionTemplateLib/access/src/Function.cpp index 56311e36..d705e344 100644 --- a/ReflectionTemplateLib/access/src/Function.cpp +++ b/ReflectionTemplateLib/access/src/Function.cpp @@ -5,7 +5,17 @@ namespace rtl { namespace access { - Function::Function(const std::string& pNamespace, const std::string& pRecord, + /* @constructor: Function() + @params: pNamespace - given namespace while registering the type. + * pRecord - given class/struct name, empty if this 'Function' represents a non-member functor + * pFunction - given name of the function as string. + * pFunctorId - 'FunctorId', generated for every functor being registered. + * pRecordTypeId - type id of class/struct if the functor is member-function, '0' for non-member-functions. + * pQualifier - whether the member-function is const or non-const. TypeQ::None for non-member-functions. + * 'Function' object is created for every functor (member/non-member) being registered. + * if the functor is already registered, duplicate 'Function' object is created but the functor is not pushed in + to functor table, instead the already existing functor's index is assigned to 'FunctorId'. + */ Function::Function(const std::string& pNamespace, const std::string& pRecord, const std::string& pFunction, const detail::FunctorId& pFunctorId, const std::size_t pRecordTypeId, const TypeQ pQualifier) : m_qualifier(pQualifier) @@ -17,7 +27,15 @@ namespace rtl { } - Function::Function(const Function& pOther, const detail::FunctorId& pFunctorId, + /* @constructor: Function() + @params: pOther - 'Function' object associated with a constructor. + * pFunctorId - 'FunctorId', object associated with a destructor. + * pFunctorName - name of the destructor. + * this constructor is only called to create 'Function' object associated with destructor. + * the destructor 'FunctorId' is added to the 'Function' object associated with a constructor while registration. + * the very first registration of constructor adds the destructor in the functor table and sends its 'FunctorId' + with the 'Function' object associated with a constructor. + */ Function::Function(const Function& pOther, const detail::FunctorId& pFunctorId, const std::string& pFunctorName) : m_qualifier(pOther.m_qualifier) , m_recordTypeId(pOther.m_recordTypeId) @@ -36,7 +54,7 @@ namespace rtl { * given signatureId is compared against the signatureId of all overloads registered. */ const std::size_t Function::hasSignatureId(const std::size_t& pSignatureId) const { - //simple linear-search, most efficient for small set of elements. + //simple linear-search, efficient for small set of elements. for (const auto& functorId : m_functorIds) { if (functorId.getSignatureId() == pSignatureId) { return functorId.getIndex(); @@ -49,12 +67,12 @@ namespace rtl { /* @method: addOverload() @param: 'Function' object * every 'Function' object produced while registration will have a single 'FunctorId' object, except constructors. - * for overloads registered with the same name, the 'FunctorId' from the other 'Function' object will be accumlated in one. + * for overloads, registered with the same name, the 'FunctorId' from the 'pOtherFunc' object will be added to this. * if the same functor is registered again with the same name, it will be ignored. */ void Function::addOverload(const Function& pOtherFunc) const { const std::size_t& otherFuncSignId = pOtherFunc.m_functorIds[0].getSignatureId(); - //simple linear-search, most efficient for small set of elements. + //simple linear-search, efficient for small set of elements. for (const auto& functorId : m_functorIds) { if (functorId.getSignatureId() == otherFuncSignId) { return; //ignore and return if its already registered. diff --git a/ReflectionTemplateLib/access/src/Instance.cpp b/ReflectionTemplateLib/access/src/Instance.cpp index c1d838a9..649c9e9d 100644 --- a/ReflectionTemplateLib/access/src/Instance.cpp +++ b/ReflectionTemplateLib/access/src/Instance.cpp @@ -8,58 +8,93 @@ namespace { + //global, used to assign to shared pointer with custom deleter. static std::size_t g_instanceCount = 0; } namespace rtl { - namespace access - { - const bool Instance::isEmpty() const { - return (!m_anyObject.has_value()); - } - - - const bool Instance::isConst() const { - return (m_qualifier == TypeQ::Const); - } - - - std::size_t Instance::getInstanceCount() { - return g_instanceCount; - } - - - void Instance::makeConst(const bool& pCastAway) { - m_qualifier = (pCastAway ? TypeQ::Mute : TypeQ::Const); - } - - - Instance::Instance() - : m_qualifier(TypeQ::None) - , m_typeId(detail::TypeId<>::None) { - } - - - Instance::Instance(const Instance& pOther) - : m_qualifier(pOther.m_qualifier) - , m_typeId(pOther.m_typeId) - , m_anyObject(pOther.m_anyObject) - , m_destructor(pOther.m_destructor) { - } - - - Instance::Instance(const std::any& pRetObj, const RStatus& pStatus, const Function& pDctor) - : m_qualifier(TypeQ::Mute) - , m_typeId(pStatus.getTypeId()) - , m_anyObject(pRetObj) - , m_destructor(&g_instanceCount, [=](void* ptr) - { - pDctor(pRetObj); - (*static_cast(ptr))--; - }) - { - g_instanceCount++; - } - } + namespace access + { + /* @method: isEmpty() + @return: bool + * checks if std::any object has value or not. + * objects constructed via reflection is held by std::any (instead of void*) + * if reflected constructor call fails, 'Insatnce' object returned with empty 'm_anyObject'. + */ const bool Instance::isEmpty() const { + return (!m_anyObject.has_value()); + } + + + /* @method: isConst() + @return: bool + * tells how the object held by 'm_anyObject' should be treated. + * every object constructed via reflected constructor call is a non-const object pointer. + * it can be made to treated as const by calling Instance::makeConst(). + */ const bool Instance::isConst() const { + return (m_qualifier == TypeQ::Const); + } + + + /* @method: getInstanceCount() + @return: std::size_t (g_instanceCount). + * returns the number of objects constructed via reflected constructor call. + * g_instanceCount is incremented only on successful reflected constructor call. + * g_instanceCount is decremented only when reflected destructor call. + */ std::size_t Instance::getInstanceCount() { + return g_instanceCount; + } + + + /* @method: makeConst() + @param: bool, (true by default) + * objects constructed via reflected constructor call, held by 'm_anyObject' as a non-const object pointer. + * 'm_qualifier' indicates how the object should be treated- as const or non-const. + * if 'm_qualifier' is TypeQ::Const, only const member function will be called on the object held by 'm_anyObject' + * if 'm_qualifier' is TypeQ::Mute,, only non-const member function will be called on the objject held by 'm_anyObject' + */ void Instance::makeConst(const bool& pCastAway) { + m_qualifier = (pCastAway ? TypeQ::Mute : TypeQ::Const); + } + + /* @constructor: Instance() + * creates 'Instance' with empty 'm_anyObject'. + * 'm_typeId' will be zero which indicates no-type. + * this constructor is called only when reflected constructor call fails. + */ Instance::Instance() + : m_qualifier(TypeQ::None) + , m_typeId(detail::TypeId<>::None) { + } + + //copy-constructor, public access. + Instance::Instance(const Instance& pOther) + : m_qualifier(pOther.m_qualifier) + , m_typeId(pOther.m_typeId) + , m_anyObject(pOther.m_anyObject) + , m_destructor(pOther.m_destructor) { + } + + + /* @constructor: Instance() + @params: 'const std::any&', contains pointer to the allocated object via reflection constructor call. + * 'const RStatus&', status returned via reflection constructor call. + * 'const Function&', callable 'Function', calls the reflecetd destructor. + * creates 'Instance' containing pointer to the allocated object via reflection constructor call. + * this constructor is called only on successful object creation on heap via reflected constructor call. + * 'm_destructor' (shared_ptr) is given a custom deleter, which calls destructor on the allocated(via reflection) object. + * 'm_destructor' holds a dummy void* pointer (address of 'g_instanceCount'), for which is a primitive type. + * this is done to avoid dynamic allocation of 'Instance' object to manage it with 'shared_ptr'. + * shared_ptr('m_destructor') holds the dummy void* but calls the actual destructor which destroys the object constructed(via reflection). + */ Instance::Instance(const std::any& pRetObj, const RStatus& pStatus, const Function& pDctor) + : m_qualifier(TypeQ::Mute) + , m_typeId(pStatus.getTypeId()) + , m_anyObject(pRetObj) + , m_destructor(&g_instanceCount, [=](void* ptr) + { + pDctor(pRetObj); + (*static_cast(ptr))--; + }) + { + g_instanceCount++; + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/FunctorId.h b/ReflectionTemplateLib/detail/inc/FunctorId.h index 2e2af572..dfefe6f9 100644 --- a/ReflectionTemplateLib/detail/inc/FunctorId.h +++ b/ReflectionTemplateLib/detail/inc/FunctorId.h @@ -3,42 +3,60 @@ #include "TypeId.h" #include "Constants.h" -namespace rtl +namespace rtl { - namespace detail - { - class FunctorId - { - const std::size_t m_index; - const std::size_t m_returnId; - const std::size_t m_recordId; - const std::size_t m_containerId; - const std::string m_signature; - - public: - - FunctorId() - : m_index(-1) - , m_returnId(TypeId<>::None) - , m_recordId(TypeId<>::None) - , m_containerId(TypeId<>::None) - , m_signature("") { - } - - FunctorId(const std::size_t& pIndex, const std::size_t& pReturnId, - const std::size_t& pRecordId, const std::size_t& pContainerId, const std::string& pSignature) - : m_index(pIndex) - , m_returnId(pReturnId) - , m_recordId(pRecordId) - , m_containerId(pContainerId) - , m_signature(pSignature) { - } - - GETTER(std::size_t, Index, m_index) - GETTER(std::size_t, SignatureId, m_containerId) - GETTER(std::string, SignatureStr, m_signature) + namespace detail + { + /* @class: FunctorId + * 'FunctorId' object is generated for every functor (member/non-member function pointer) registered. + * acts as a hash-key to lookup a particular functor in the functor-table. + * first, using 'm_containerId', the functor-table container is found. + * once table is found, the functor is accessed at index 'm_index', (never fails, noexcept) + * 'FunctorId' generated for a each functor is unique, even for overloaded functions. + * multiple registartion of same functor will generate same duplicate 'FunctorId'. + */ class FunctorId + { + //index of the functor in the functor-table. + const std::size_t m_index; + + //return type-id of the functor registered. + const std::size_t m_returnId; + + //if functor is a member-function, type id of class/struct it belongs to. + const std::size_t m_recordId; + + //containerId of the functor-table. + const std::size_t m_containerId; + + //signature(types/count) of functor as string. platform dependent, may not be very much readable format. + const std::string m_signature; + + public: + + FunctorId() + : m_index(-1) + , m_returnId(TypeId<>::None) + , m_recordId(TypeId<>::None) + , m_containerId(TypeId<>::None) + , m_signature("") { + } + + FunctorId(const std::size_t& pIndex, + const std::size_t& pReturnId, const std::size_t& pRecordId, + const std::size_t& pContainerId, const std::string& pSignature) + : m_index(pIndex) + , m_returnId(pReturnId) + , m_recordId(pRecordId) + , m_containerId(pContainerId) + , m_signature(pSignature) { + } + + GETTER(std::size_t, Index, m_index) + GETTER(std::size_t, SignatureId, m_containerId) + GETTER(std::string, SignatureStr, m_signature) - std::size_t getHashCode() const; - }; - } + //get a unique hascode representing a functor. + std::size_t getHashCode() const; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/src/CxxReflection.cpp b/ReflectionTemplateLib/detail/src/CxxReflection.cpp index 4304845e..536e698e 100644 --- a/ReflectionTemplateLib/detail/src/CxxReflection.cpp +++ b/ReflectionTemplateLib/detail/src/CxxReflection.cpp @@ -58,8 +58,8 @@ namespace rtl { /* @method: addMethod @params: MethodMap, Function - * adds the 'Function' object as 'Method' object the the method map contained by 'Record' object. - * if the function name already exists in the map, then 'FunctorId' from the source 'Function' object is added to already existing 'Function' object. + * adds the 'Function' object as 'Method' object in MethodMap, contained by 'Record' object. + * if the function name already exists in the map, then 'FunctorId' from the param 'pFunction' is added to already existing 'Function'. * if a 'Function' object represents a Constructor, it might have the destructor 'FunctorId' as well. * if destructor 'FunctorId' is found, destructor 'Function' object is created and added to the 'MethodMap'. */ void CxxReflection::addMethod(MethodMap& pMethodMap, const access::Function& pFunction) @@ -70,7 +70,7 @@ namespace rtl { { auto& functorIds = pFunction.getFunctorIds(); /* This condition will be true only in case that 'Function' object represents a constructor - and has more that one 'FunctorId'. every other function registered will have only one 'FunctorId'. + and has more than one 'FunctorId'. every other function registered will have only one 'FunctorId'. */ if (functorIds.size() > 1) { const auto& dctorName = CtorName::dctor(pFunction.getRecordName()); @@ -82,7 +82,7 @@ namespace rtl { //remove the destructor 'FunctorId' from the constructor's 'FunctorId' vector. functorIds.pop_back(); } - //construct 'Method' obejct from 'Function' object and add. + //construct 'Method' obejct and add. pMethodMap.emplace(fname, access::Method(pFunction)); } else { diff --git a/ReflectionTemplateLib/detail/src/FunctorId.cpp b/ReflectionTemplateLib/detail/src/FunctorId.cpp index f544950f..06bb9627 100644 --- a/ReflectionTemplateLib/detail/src/FunctorId.cpp +++ b/ReflectionTemplateLib/detail/src/FunctorId.cpp @@ -3,14 +3,24 @@ namespace rtl { - namespace detail - { - std::size_t FunctorId::getHashCode() const - { - return std::stoull(std::to_string(m_containerId) + - std::to_string(m_index) + - std::to_string(m_recordId) + - std::to_string(m_returnId)); - } - } + namespace detail + { + /* @method: getHashCode() + @return: std::size_t (a unique hash-code for a functor) + * 'm_containerId' will be same for functors(non-member) with same signatures. + * for member functions, a functor will have three atrributes + - signature + - whether it is const or non-const + - class/struct type + 'm_containerId' will be same for functors with same above attributes. + * every functor will have a distinct index in the functor table. + * so, combination of m_containerId & m_index is unique for every functor. + */ std::size_t FunctorId::getHashCode() const + { + return std::stoull(std::to_string(m_containerId) + + std::to_string(m_index) + + std::to_string(m_recordId) + + std::to_string(m_returnId)); + } + } } \ No newline at end of file From df419e97ea846127f5a22b8a8aab4d777397a6c0 Mon Sep 17 00:00:00 2001 From: neeraj31285 Date: Tue, 30 Jul 2024 15:24:50 +0530 Subject: [PATCH 9/9] comments added --- .../src/ConstMethodOverloadTests.cpp | 36 +++ CxxTestProject/inc/Person.h | 2 + CxxTestProject/src/Person.cpp | 6 + CxxTypeRegistration/inc/TestUtilsPerson.h | 1 + CxxTypeRegistration/src/MyReflection.cpp | 1 + ReflectionTemplateLib/access/inc/CxxMirror.h | 14 +- ReflectionTemplateLib/access/inc/Function.hpp | 4 +- ReflectionTemplateLib/access/inc/Method.h | 4 +- ReflectionTemplateLib/access/inc/Method.hpp | 21 +- ReflectionTemplateLib/access/inc/RStatus.h | 2 +- ReflectionTemplateLib/access/inc/Record.hpp | 11 +- ReflectionTemplateLib/access/src/Function.cpp | 16 +- ReflectionTemplateLib/builder/inc/Builder.hpp | 3 +- ReflectionTemplateLib/builder/inc/Reflect.h | 4 +- ReflectionTemplateLib/builder/inc/Reflect.hpp | 21 +- .../detail/inc/CallReflector.h | 55 ++-- .../detail/inc/FunctorContainer.h | 117 ++++---- ReflectionTemplateLib/detail/inc/FunctorId.h | 2 +- .../detail/inc/MethodContainer.h | 268 +++++++++-------- .../detail/inc/ReflectionBuilder.h | 74 +++-- .../detail/inc/ReflectionBuilder.hpp | 157 ++++++---- .../detail/inc/SetupConstructor.h | 41 ++- .../detail/inc/SetupConstructor.hpp | 274 +++++++++++------- .../detail/inc/SetupFunction.h | 32 +- .../detail/inc/SetupFunction.hpp | 111 ++++--- .../detail/inc/SetupMethod.h | 15 +- .../detail/inc/SetupMethod.hpp | 213 +++++++++----- ReflectionTemplateLib/detail/inc/TypeId.h | 112 +++---- ReflectionTemplateLib/detail/inc/TypeId.hpp | 1 + .../detail/src/FunctorId.cpp | 2 +- .../detail/src/TypeIdInitializer.cpp | 3 + 31 files changed, 1000 insertions(+), 623 deletions(-) diff --git a/CxxReflectionTests/src/ConstMethodOverloadTests.cpp b/CxxReflectionTests/src/ConstMethodOverloadTests.cpp index a3560b46..f6d80fd7 100644 --- a/CxxReflectionTests/src/ConstMethodOverloadTests.cpp +++ b/CxxReflectionTests/src/ConstMethodOverloadTests.cpp @@ -69,6 +69,42 @@ namespace rtl_tests } + TEST(ConstMethodOverload, const_method_no_overload_call_on_const_target_returns_string) + { + { + CxxMirror& cxxMirror = MyReflection::instance(); + + optional recOpt = cxxMirror.getRecord(person::class_); + ASSERT_TRUE(recOpt.has_value()); + + const Record& classPerson = recOpt.value(); + optional updateLastName = classPerson.getMethod(person::str_updateLastName); + ASSERT_TRUE(updateLastName); + + const std::string firstName = person::FIRST_NAME; + auto [status, personObj] = classPerson.instance(firstName); + + ASSERT_TRUE(status); + ASSERT_FALSE(personObj.isEmpty()); + + personObj.makeConst(); + ASSERT_TRUE(personObj.isConst()); + + optional getFirstName = classPerson.getMethod(person::str_getFirstName); + ASSERT_TRUE(getFirstName); + + const RStatus& rstatus = getFirstName->on(personObj).call(); + ASSERT_TRUE(rstatus); + ASSERT_TRUE(rstatus.isOfType()); + + const std::string retStr = std::any_cast(rstatus.getReturn()); + ASSERT_EQ(retStr, firstName); + } + EXPECT_TRUE(person::assert_zero_instance_count()); + EXPECT_TRUE(Instance::getInstanceCount() == 0); + } + + TEST(ConstMethodOverload, const_method_string_call_on_const_target) { { diff --git a/CxxTestProject/inc/Person.h b/CxxTestProject/inc/Person.h index 5e009244..b429b6d1 100644 --- a/CxxTestProject/inc/Person.h +++ b/CxxTestProject/inc/Person.h @@ -22,6 +22,8 @@ class Person void updateAddress() const; + std::string getFirstName() const; + void updateAddress(std::string pAddress); void updateAddress(std::string pAddress) const; diff --git a/CxxTestProject/src/Person.cpp b/CxxTestProject/src/Person.cpp index 0ced07ef..ab5ebefd 100644 --- a/CxxTestProject/src/Person.cpp +++ b/CxxTestProject/src/Person.cpp @@ -62,6 +62,12 @@ void Person::updateAddress() const } +std::string Person::getFirstName() const +{ + return m_firstName; +} + + const bool Person::operator==(const Person& pOther) const { return (m_address == pOther.m_address && m_firstName == pOther.m_firstName && m_lastName == pOther.m_lastName); diff --git a/CxxTypeRegistration/inc/TestUtilsPerson.h b/CxxTypeRegistration/inc/TestUtilsPerson.h index 69f6d72f..3098b716 100644 --- a/CxxTypeRegistration/inc/TestUtilsPerson.h +++ b/CxxTypeRegistration/inc/TestUtilsPerson.h @@ -21,6 +21,7 @@ namespace test_utils static constexpr const char* class_ = "Person"; static constexpr const char* str_getProfile = "getProfile"; static constexpr const char* str_getDefaults = "getDefaults"; + static constexpr const char* str_getFirstName = "getFirstName"; static constexpr const char* str_updateAddress = "updateAddress"; static constexpr const char* str_updateLastName = "updateLastName"; diff --git a/CxxTypeRegistration/src/MyReflection.cpp b/CxxTypeRegistration/src/MyReflection.cpp index 381a3d01..99d015d0 100644 --- a/CxxTypeRegistration/src/MyReflection.cpp +++ b/CxxTypeRegistration/src/MyReflection.cpp @@ -69,6 +69,7 @@ CxxMirror& MyReflection::instance() Reflect().record(person::class_).constructor().build(), //copy constructor taking const ref argument. Reflect().record(person::class_).method(person::str_updateAddress).build(&Person::updateAddress), Reflect().record(person::class_).method(person::str_updateAddress).build(&Person::updateAddress), + Reflect().record(person::class_).methodConst(person::str_getFirstName).build(&Person::getFirstName), Reflect().record(person::class_).methodConst(person::str_updateLastName).build(&Person::updateLastName), //const method registration, 'methodConst()' function must be used. compiler error otherwise. Reflect().record(person::class_).methodConst(person::str_updateAddress).build(&Person::updateAddress), Reflect().record(person::class_).methodConst(person::str_updateAddress).build(&Person::updateAddress), //overloaded method based on 'const'. diff --git a/ReflectionTemplateLib/access/inc/CxxMirror.h b/ReflectionTemplateLib/access/inc/CxxMirror.h index 4b82fefe..81b49cde 100644 --- a/ReflectionTemplateLib/access/inc/CxxMirror.h +++ b/ReflectionTemplateLib/access/inc/CxxMirror.h @@ -20,13 +20,13 @@ namespace rtl { * all the type registration is done while constructing its object. * its objects can be createed locally and will be destroyed as regular object, at scope's end. * deleted copy constructor and assignment operator, can only be passed around as reference or wrapped in a smart pointer. - * the inherited data members are freed upon destruction, except the functors (function/method pointer) tables, they have static lifetime. - * functor tables are not member of this or base class, this class contains 'Function' objects which is a hash-key for looking up a particular functor. - * creating multiple objects of CxxMirror and registring the same functor will not increase the functor tables size. - * once a functor is registered, no entry will be added to the functor table for the same functor, it acts as a set. - * registring the same functor will create duplicate hash-key 'Function' object, which will be ignored if in the same 'CxxMirror' object. - if two different 'CxxMirror' objects are created and registering the same functor, the functor table will have only one entry for the functor - but two duplicate 'Function' objects will be created, held by respective 'CxxMirror' object. + * the inherited data members are freed upon destruction, except the 'functor-containers', they have static lifetime. + * 'functor-containers' are not member of this or base class, base only contains 'Function' objects which is a hash-key for looking up a particular functor. + * creating multiple objects of CxxMirror and registring the same functor will not increase the 'functor-container' size. + * once a functor is registered, no entry will be added to the 'functor-container' for the same functor. + * registering the same functor will create duplicate hash-key 'Function' object, which will be ignored if in the same 'CxxMirror' object. + if two different 'CxxMirror' objects are created and registering the same functor, the functor-container will have only one entry for the functor + but two identical 'Function' objects will be created, held by respective 'CxxMirror' object. */ class CxxMirror : public detail::CxxReflection { public: diff --git a/ReflectionTemplateLib/access/inc/Function.hpp b/ReflectionTemplateLib/access/inc/Function.hpp index 6874f1bd..9bf7f023 100644 --- a/ReflectionTemplateLib/access/inc/Function.hpp +++ b/ReflectionTemplateLib/access/inc/Function.hpp @@ -17,7 +17,7 @@ namespace rtl { */ template inline const bool Function::hasSignature() const { - //hasSignatureId() returns the index of functor in functor table, which cannot be '-1'. + //hasSignatureId() returns the index of the 'lambda' in functor-container, which cannot be '-1'. return (hasSignatureId(detail::FunctorContainer<_arg0, _args...>::getContainerId()) != -1); } @@ -28,7 +28,7 @@ namespace rtl { */ template<> inline const bool Function::hasSignature() const { - //hasSignatureId() returns the index of functor in functor table, which cannot be '-1'. + //hasSignatureId() returns the index of 'lambda' in functor-container, which cannot be '-1'. return (hasSignatureId(detail::FunctorContainer<>::getContainerId()) != -1); } diff --git a/ReflectionTemplateLib/access/inc/Method.h b/ReflectionTemplateLib/access/inc/Method.h index 60a99543..f3610c6e 100644 --- a/ReflectionTemplateLib/access/inc/Method.h +++ b/ReflectionTemplateLib/access/inc/Method.h @@ -71,10 +71,10 @@ namespace rtl { */ class Method : public Function { //private ctor, called by 'Record' class. - Method(const Function& pFunction); + explicit Method(const Function& pFunction); //private ctor, called by 'Record' class. - Method(const Function& pFunction, const detail::FunctorId& pFunctorId, const std::string& pFunctorName); + explicit Method(const Function& pFunction, const detail::FunctorId& pFunctorId, const std::string& pFunctorName); //invokes the constructor associated with this 'Method' template diff --git a/ReflectionTemplateLib/access/inc/Method.hpp b/ReflectionTemplateLib/access/inc/Method.hpp index 3c953477..40ea066e 100644 --- a/ReflectionTemplateLib/access/inc/Method.hpp +++ b/ReflectionTemplateLib/access/inc/Method.hpp @@ -17,7 +17,7 @@ namespace rtl @params: params... (corresponding to functor associated with 'm_method') @return: RStatus, indicating success of the reflected call. * invokes non-static-member-function functor associated with 'm_method' on object 'm_target'. - */ template + */ template template inline RStatus MethodInvoker<_type>::call(_args ...params) const noexcept { @@ -27,7 +27,7 @@ namespace rtl } if (m_target.getTypeId() != m_method.getRecordTypeId()) { - //if the m_target's type-id & type-id of the 'class/struct' owner of the associated functor(m_method's) do not match. + //if the m_target's type-id & type-id of the 'class/struct' owner of the associated functor(m_method's) do not match. return RStatus(Error::InstanceTypeMismatch); } @@ -40,7 +40,7 @@ namespace rtl case TypeQ::Const: return m_method.invokeConst(m_target, params...); } - //only an empty 'Instance' will have TypeQ::None. + //only an empty 'Instance' will have TypeQ::None. return RStatus(Error::EmptyInstance); } @@ -60,7 +60,7 @@ namespace rtl namespace access - { + { /* @method: on() @return: MethodInvoker * accepts no arguments for 'target', since associated functor is static-member-functions. @@ -70,7 +70,10 @@ namespace rtl } - inline const MethodInvoker Method::on(const Instance& pTarget) const + /* @method: on() + @return: MethodInvoker + * accepts 'pTarget', which contains the actual object on which the member-function functor associated with 'this' is invoked. + */ inline const MethodInvoker Method::on(const Instance& pTarget) const { return MethodInvoker(*this, pTarget); } @@ -88,9 +91,9 @@ namespace rtl /* @method: invokeStatic() - @params: variable arguments. - @return: RStatus - * with given arguments, calls the static-member-function functor associated with this 'Method'. + @params: variable arguments. + @return: RStatus + * with given arguments, calls the static-member-function functor associated with this 'Method'. */ template inline RStatus Method::invokeStatic(_args ...params) const { @@ -173,7 +176,7 @@ namespace rtl return detail::MethodContainer::forwardCall(pTarget.get(), index, params...); } else { - //if no such member-functor is found in non-const MethodContainer, check if such functor is present in const MethodContainer. + //if no such member-functor is found in non-const MethodContainer, check if such functor is present in const MethodContainer and call. return invokeConst(pTarget, params...); } } diff --git a/ReflectionTemplateLib/access/inc/RStatus.h b/ReflectionTemplateLib/access/inc/RStatus.h index ac4c5b71..d61d8be9 100644 --- a/ReflectionTemplateLib/access/inc/RStatus.h +++ b/ReflectionTemplateLib/access/inc/RStatus.h @@ -32,7 +32,7 @@ namespace rtl //used when the reflected call doesn't have any return value, or in case of call failure. RStatus(const Error pCallStatus); - //used when the reflected call returns a value, always in case of no call failure. + //used when the reflected call returns a value, called only in case of no call failure. RStatus(const std::any& pRetObj, const std::size_t pTypeId, const TypeQ pQualifier); GETTER(std::any, Return, m_returnObj) diff --git a/ReflectionTemplateLib/access/inc/Record.hpp b/ReflectionTemplateLib/access/inc/Record.hpp index 109b9cdd..42a47fec 100644 --- a/ReflectionTemplateLib/access/inc/Record.hpp +++ b/ReflectionTemplateLib/access/inc/Record.hpp @@ -22,8 +22,7 @@ namespace rtl { */ template inline const std::pair Record::instance(_ctorArgs ...params) const { - const std::string& ctor = CtorName::ctor(m_recordName); - const auto& itr = m_methods.find(ctor); + const auto& itr = m_methods.find(CtorName::ctor(m_recordName)); //if registered constructor is found for the class/struct represented by this 'Record' object. if (itr != m_methods.end()) { @@ -34,11 +33,11 @@ namespace rtl { //if status is 'true', object construction is successful. if (status) { - //get the destructor method, which is gauranteed to be present, if at least one constructor is registered. - const std::string& dctor = CtorName::dctor(m_recordName); + //get the destructor 'Function', which is gauranteed to be present, if at least one constructor is registered. + const Function dctor = *getMethod(CtorName::dctor(m_recordName)); - //construct the 'Instance' object, assigning the destructor, its lifetime is managed via std::shared_ptr. - return std::make_pair(status, Instance(status.getReturn(), status, *getMethod(dctor))); + //construct the 'Instance' object, assigning the destructor as custom deleter, its lifetime is managed via std::shared_ptr. + return std::make_pair(status, Instance(status.getReturn(), status, dctor)); } //if reflected call fails, return with empty 'Instance'. return std::make_pair(status, Instance()); diff --git a/ReflectionTemplateLib/access/src/Function.cpp b/ReflectionTemplateLib/access/src/Function.cpp index d705e344..0402d4ef 100644 --- a/ReflectionTemplateLib/access/src/Function.cpp +++ b/ReflectionTemplateLib/access/src/Function.cpp @@ -13,17 +13,15 @@ namespace rtl { * pRecordTypeId - type id of class/struct if the functor is member-function, '0' for non-member-functions. * pQualifier - whether the member-function is const or non-const. TypeQ::None for non-member-functions. * 'Function' object is created for every functor (member/non-member) being registered. - * if the functor is already registered, duplicate 'Function' object is created but the functor is not pushed in - to functor table, instead the already existing functor's index is assigned to 'FunctorId'. */ Function::Function(const std::string& pNamespace, const std::string& pRecord, const std::string& pFunction, const detail::FunctorId& pFunctorId, const std::size_t pRecordTypeId, const TypeQ pQualifier) : m_qualifier(pQualifier) , m_recordTypeId(pRecordTypeId) - , m_functorIds({ pFunctorId }) , m_record(pRecord) , m_function(pFunction) - , m_namespace(pNamespace) { + , m_namespace(pNamespace) + , m_functorIds({ pFunctorId }) { } @@ -33,16 +31,16 @@ namespace rtl { * pFunctorName - name of the destructor. * this constructor is only called to create 'Function' object associated with destructor. * the destructor 'FunctorId' is added to the 'Function' object associated with a constructor while registration. - * the very first registration of constructor adds the destructor in the functor table and sends its 'FunctorId' - with the 'Function' object associated with a constructor. + * the very first registration of constructor adds the destructor lambda in the functor-container and sends its + 'FunctorId' with the 'Function' object associated with a constructor. */ Function::Function(const Function& pOther, const detail::FunctorId& pFunctorId, const std::string& pFunctorName) : m_qualifier(pOther.m_qualifier) , m_recordTypeId(pOther.m_recordTypeId) - , m_functorIds({ pFunctorId }) , m_record(pOther.m_record) , m_function(pFunctorName) - , m_namespace(pOther.m_namespace) { + , m_namespace(pOther.m_namespace) + , m_functorIds({ pFunctorId }) { } @@ -75,7 +73,7 @@ namespace rtl { //simple linear-search, efficient for small set of elements. for (const auto& functorId : m_functorIds) { if (functorId.getSignatureId() == otherFuncSignId) { - return; //ignore and return if its already registered. + return; //ignore and return since its already registered. } } diff --git a/ReflectionTemplateLib/builder/inc/Builder.hpp b/ReflectionTemplateLib/builder/inc/Builder.hpp index 054db68e..46bba871 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.hpp +++ b/ReflectionTemplateLib/builder/inc/Builder.hpp @@ -151,8 +151,7 @@ namespace rtl { * template params <...>, explicitly specified. * calling with zero template params will build the default constructor ie, 'RecordBuilder<_recordType>::constructor()' */ template - inline constexpr const access::Function - Builder::build() const + inline constexpr const access::Function Builder::build() const { //this code-block is retained by compiler, if copy constructor with non-const ref('_recordType&') is being registered. if constexpr (std::is_same_v<_recordType&, typename detail::TypeId<_signature...>::HEAD>) diff --git a/ReflectionTemplateLib/builder/inc/Reflect.h b/ReflectionTemplateLib/builder/inc/Reflect.h index 291b9188..341ca0c4 100644 --- a/ReflectionTemplateLib/builder/inc/Reflect.h +++ b/ReflectionTemplateLib/builder/inc/Reflect.h @@ -15,10 +15,10 @@ namespace rtl { * provides interface to register all kinds of functions (member/non-member). */ class Reflect { - //name of the class, struct being registered as string. + //name of the class, struct being registered. std::string m_record; - //name of the namespace being registered as string. + //name of the namespace being registered. std::string m_namespace; public: diff --git a/ReflectionTemplateLib/builder/inc/Reflect.hpp b/ReflectionTemplateLib/builder/inc/Reflect.hpp index 99d858a4..d1147033 100644 --- a/ReflectionTemplateLib/builder/inc/Reflect.hpp +++ b/ReflectionTemplateLib/builder/inc/Reflect.hpp @@ -6,11 +6,11 @@ namespace rtl { - namespace builder + namespace builder { inline Reflect::Reflect() : m_record("") - //If no namespace is given, types are kept under default namespace name: NAMESPACE_GLOBAL. + //If no namespace is given, types are kept under default name: NAMESPACE_GLOBAL. , m_namespace(NAMESPACE_GLOBAL) { } @@ -18,11 +18,12 @@ namespace rtl { /* @function: nameSpace() @param: std::string, name of the 'namespace' as string. @return: '*this', Reflect. - * used to group registered function, class/struct under namespace name. - * its a logical grouping of registered types under a 'namespace' name. - * optional- function, class/struct can be registered without given namespace name, even if they exists in one. - * if types are registered with namespace name, then that name should be passed when retriving the objects from cxxMirror objects. - * check functions CxxMirror::getFunction("name_space", "func_name") & CxxMirror::getFunction("name_space","class_name"). + * used to group registered function, class/struct under a namespace name. + * its an internal grouping of registered types under a 'namespace' name. + * providing a namespace is optional. registration can be done without a namespace name, even if a type exists in one. + * if types are registered with 'namespace' name, then it must be passed when retriving the objects from 'CxxMirror', + check functions, CxxMirror::getFunction("name_space", "func_name") & CxxMirror::getRecord("name_space","class_name"), + if no namespace is given, then CxxMirror::getFunction("func_name") & CxxMirror::getRecord("class_name") */ inline Reflect& Reflect::nameSpace(const std::string& pNamespace) { m_namespace = pNamespace; @@ -31,7 +32,7 @@ namespace rtl { /* @function: function() - @param: std::string, name of function as string. + @param: std::string (name of the function). @return: Builder * registers only non-member functions. * the 'build(..)' called on return object accepts non-member function pointer only. @@ -44,7 +45,7 @@ namespace rtl { /* @function: record() - @param: std::string, name of class/struct as string. + @param: std::string (name of class/struct) @return: RecordBuilder<_recordType> * provides object of 'RecordBuilder', which provides interface to registers member functions of class/struct of '_recordType'. * the 'build(..)' called on return object accepts non-member function pointer only. @@ -57,7 +58,7 @@ namespace rtl { /* @method: function<...>() - @param: std::string, name of function as string. + @param: std::string (name of function) @return: Builder * registers only non-member functions. * used for registering overloads, if unique member function, use non-templated version 'function()'. diff --git a/ReflectionTemplateLib/detail/inc/CallReflector.h b/ReflectionTemplateLib/detail/inc/CallReflector.h index 798efc86..8d5b355a 100644 --- a/ReflectionTemplateLib/detail/inc/CallReflector.h +++ b/ReflectionTemplateLib/detail/inc/CallReflector.h @@ -5,27 +5,42 @@ namespace rtl { - namespace access { - class RStatus; - } + namespace access { + //forward decl. + class RStatus; + } - namespace detail - { - template - struct CallReflector - { - template - static access::RStatus forwardCall(std::size_t pFunctorIndex, _params..._args) - { - return _derivedType::getFunctors().at(pFunctorIndex)(_args...); - } + namespace detail + { + /* @struct: CallReflector + @param: _derivedType (type which inherits this class) + * retrieves the lambda at given index and calls it with the arguments supplied. + * deriving classes are, MethodContainer & FunctorContainer. + */ template + struct CallReflector + { + /* @method: forwardCall + @param: pFunctorIndex (index of the lambda), _args...(arguments to be passed to that lambda) + * gets the lambda vector from '_derivedType' and calls the lambda at given index with '_args'. + * this 'forwardCall' is for calling lambda containing non-member-function and static-member-function functors. + */ template + static access::RStatus forwardCall(std::size_t pFunctorIndex, _params..._args) + { + //'getFunctors()' must be implemented by _derivedType (FunctorContainer). + return _derivedType::getFunctors().at(pFunctorIndex)(_args...); + } - template - static access::RStatus forwardCall(const std::any& pTarget, std::size_t pFunctorIndex, _params..._args) - { - return _derivedType::getMethodFunctors().at(pFunctorIndex)(pTarget, _args...); - } - }; - } + /* @method: forwardCall + @param: pFunctorIndex (index of the lambda), _args...(arguments to be passed to that lambda) + * gets the lambda vector from '_derivedType' and calls the lambda at given index with '_args'. + * this 'forwardCall' is for calling lambda containing member-function functors. + */ template + static access::RStatus forwardCall(const std::any& pTarget, std::size_t pFunctorIndex, _params..._args) + { + //'getMethodFunctors()' is implemented by _derivedType (MethodContainer) + return _derivedType::getMethodFunctors().at(pFunctorIndex)(pTarget, _args...); + } + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/FunctorContainer.h b/ReflectionTemplateLib/detail/inc/FunctorContainer.h index 745c0201..a43434f4 100644 --- a/ReflectionTemplateLib/detail/inc/FunctorContainer.h +++ b/ReflectionTemplateLib/detail/inc/FunctorContainer.h @@ -12,63 +12,82 @@ namespace rtl { - namespace detail - { - class ReflectionBuilder; - extern std::atomic g_containerIdCounter; + namespace detail + { + //forward decl + class ReflectionBuilder; + //unique id generator. + extern std::atomic g_containerIdCounter; - template - class FunctorContainer : public SetupFunction>, - public SetupConstructor>, - public CallReflector> - { - using FunctionLambda = std::function < access::RStatus(_signature...) >; - public: + /* @class: FunctorContainer + @param: '_signature...' (combination of any types) + * container class for holding lambda's wrapping functor, constructor/destructor calls of same signatures. + * maintains a std::vector with static lifetime. + */ template + class FunctorContainer : public SetupFunction>, + public SetupConstructor>, + public CallReflector> + { + using FunctionLambda = std::function < access::RStatus(_signature...) >; + public: - static const std::size_t& getContainerId() { - return m_containerId; - } + //every FunctorContainer<...> will have a unique-id. + static const std::size_t& getContainerId() { + return m_containerId; + } - const static std::vector& getFunctors() { - return m_functors; - } + //get the vector holding lambdas as 'const-ref' + const static std::vector& getFunctors() { + return m_functors; + } - template - static const std::string getSignatureStr(const bool pIsMember = false) { - const std::string& retStr = TypeId<_returnType>::toString(); - return (retStr + (pIsMember ? "::" : " ") + "(" + TypeId<_signature...>::toString() + ")"); - } + //get functor container type(_signature...) as string with given 'returnType'. + template + static const std::string getSignatureStr(const bool pIsMember = false) { + const std::string& retStr = TypeId<_returnType>::toString(); + return (retStr + (pIsMember ? "::" : " ") + "(" + TypeId<_signature...>::toString() + ")"); + } - private: - - static const std::size_t m_containerId; - static std::vector m_functors; + private: - static const std::size_t pushBack(const FunctionLambda& pFunctor, - std::function pGetIndex, - std::function pUpdate) - { - static std::mutex mtx; - std::lock_guard lock(mtx); + //holds unique-id + static const std::size_t m_containerId; - std::size_t index = pGetIndex(); - if (index == -1) { - index = m_functors.size(); - pUpdate(index); - m_functors.push_back(pFunctor); - } - return index; - } + //vector holding lambdas + static std::vector m_functors; - friend ReflectionBuilder; - friend SetupFunction>; - friend SetupConstructor>; - }; + /* @method: pushBack + @params: pFunctor (lambda containing functor or constructor/destructor call) + pGetIndex (lambda providing index if the functor is already registered) + pUpdate (lambda updating the already registered functors/ctor/d'tor set) + @return: index of newly added or already existing lambda in vector 'm_functors'. + */ static const std::size_t pushBack(const FunctionLambda& pFunctor, + std::function pGetIndex, + std::function pUpdate) + { + //critical section, thread safe. + static std::mutex mtx; + std::lock_guard lock(mtx); - template - const std::size_t FunctorContainer<_signature...>::m_containerId = g_containerIdCounter.fetch_add(1); + std::size_t index = pGetIndex(); + if (index == -1) { + index = m_functors.size(); + pUpdate(index); + m_functors.push_back(pFunctor); + } + return index; + } + + //friends :) + friend ReflectionBuilder; + friend SetupFunction>; + friend SetupConstructor>; + }; - template - std::vector::FunctionLambda> FunctorContainer<_signature...>::m_functors; - } + template + const std::size_t FunctorContainer<_signature...>::m_containerId = g_containerIdCounter.fetch_add(1); + + template + std::vector::FunctionLambda> FunctorContainer<_signature...>::m_functors; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/FunctorId.h b/ReflectionTemplateLib/detail/inc/FunctorId.h index dfefe6f9..b1893fde 100644 --- a/ReflectionTemplateLib/detail/inc/FunctorId.h +++ b/ReflectionTemplateLib/detail/inc/FunctorId.h @@ -28,7 +28,7 @@ namespace rtl //containerId of the functor-table. const std::size_t m_containerId; - //signature(types/count) of functor as string. platform dependent, may not be very much readable format. + //signature of functor as string. platform dependent, may not be very much readable format. const std::string m_signature; public: diff --git a/ReflectionTemplateLib/detail/inc/MethodContainer.h b/ReflectionTemplateLib/detail/inc/MethodContainer.h index 9b2e8df2..fc7d5c35 100644 --- a/ReflectionTemplateLib/detail/inc/MethodContainer.h +++ b/ReflectionTemplateLib/detail/inc/MethodContainer.h @@ -12,122 +12,158 @@ namespace rtl { - namespace detail - { - class ReflectionBuilder; - extern std::atomic g_containerIdCounter; - - template - class MethodContainer; - - template - class MethodContainer : public SetupMethod>, - public CallReflector> - { - using MethodLambda = std::function < access::RStatus(std::any, _signature...) >; - - public: - - static const std::size_t& getContainerId() { - return m_containerId; - } - - static const std::vector& getMethodFunctors() { - return m_methodPtrs; - } - - template - static const std::string getSignatureStr() { - return (TypeId<_returnType>::toString() + " " + TypeId<_recordType>::toString() + "::(" + TypeId<_signature...>::toString() + ")"); - } - - private: - - static const std::size_t m_containerId; - static std::vector m_methodPtrs; - - static const std::size_t pushBack(const MethodLambda& pFunctor, - std::function pGetIndex, - std::function pUpdateIndex) - { - static std::mutex mtx; - std::lock_guard lock(mtx); - - std::size_t index = pGetIndex(); - if (index == -1) { - index = m_methodPtrs.size(); - pUpdateIndex(index); - m_methodPtrs.push_back(pFunctor); - } - return index; - } - - friend ReflectionBuilder; - friend SetupMethod>; - }; - - template - const std::size_t MethodContainer::m_containerId = g_containerIdCounter.fetch_add(1); - - template - std::vector::MethodLambda> - MethodContainer::m_methodPtrs; - } + namespace detail + { + //forward decl + class ReflectionBuilder; + //unique id generator. + extern std::atomic g_containerIdCounter; + + template + class MethodContainer; + + /* @class: MethodContainer + @param: '_signature...' (combination of any types) + * container class for holding lambda's wrapping non-const-member-function functor calls of same signatures. + * maintains a std::vector with static lifetime. + */ template + class MethodContainer : public SetupMethod>, + public CallReflector> + { + using MethodLambda = std::function < access::RStatus(std::any, _signature...) >; + + public: + + //every MethodContainer will have a unique-id. + static const std::size_t& getContainerId() { + return m_containerId; + } + + //get the vector holding lambdas as 'const-ref' + static const std::vector& getMethodFunctors() { + return m_methodPtrs; + } + + //get container type as string + template + static const std::string getSignatureStr() { + return (TypeId<_returnType>::toString() + " " + TypeId<_recordType>::toString() + "::(" + TypeId<_signature...>::toString() + ")"); + } + + private: + + //holds unique-id + static const std::size_t m_containerId; + + //vector holding lambdas + static std::vector m_methodPtrs; + + /* @method: pushBack + @params: pFunctor (lambda containing non-const-member-function functor call) + pGetIndex (lambda providing index if the functor is already registered) + pUpdate (lambda updating the already registered functors set) + @return: index of newly added or already existing lambda in vector 'm_methodPtrs'. + */ static const std::size_t pushBack(const MethodLambda& pFunctor, + std::function pGetIndex, + std::function pUpdateIndex) + { + //critical section, thread safe. + static std::mutex mtx; + std::lock_guard lock(mtx); + + std::size_t index = pGetIndex(); + if (index == -1) { + index = m_methodPtrs.size(); + pUpdateIndex(index); + m_methodPtrs.push_back(pFunctor); + } + return index; + } + + //friends :) + friend ReflectionBuilder; + friend SetupMethod>; + }; + + template + const std::size_t MethodContainer::m_containerId = g_containerIdCounter.fetch_add(1); + + template + std::vector::MethodLambda> + MethodContainer::m_methodPtrs; + } - namespace detail - { - template - class MethodContainer : public SetupMethod>, - public CallReflector> - { - using MethodLambda = std::function < access::RStatus(std::any, _signature...) >; - - public: - - static const std::size_t& getContainerId() { - return m_containerId; - } - - static const std::vector& getMethodFunctors() { - return m_methodPtrs; - } - - template - static const std::string getSignatureStr() { - return (TypeId<_returnType>::toString() + " " + TypeId<_recordType>::toString() + "::(" + TypeId<_signature...>::toString() + ") const"); - } - - private: - - static const std::size_t m_containerId; - static std::vector m_methodPtrs; - - static const std::size_t pushBack(const MethodLambda& pFunctor, - std::function pGetIndex, - std::function pUpdateIndex) - { - static std::mutex mtx; - std::lock_guard lock(mtx); - - std::size_t index = pGetIndex(); - if (index == -1) { - index = m_methodPtrs.size(); - pUpdateIndex(index); - m_methodPtrs.push_back(pFunctor); - } - return index; - } - - friend ReflectionBuilder; - friend SetupMethod>; - }; - - template - const std::size_t MethodContainer::m_containerId = g_containerIdCounter.fetch_add(1); - - template - std::vector::MethodLambda> - MethodContainer::m_methodPtrs; - } + namespace detail + { + /* @class: MethodContainer + @param: '_signature...' (combination of any types) + * container class for holding lambda's wrapping const-member-function functor calls of same signatures. + * maintains a std::vector with static lifetime. + */ template + class MethodContainer : public SetupMethod>, + public CallReflector> + { + using MethodLambda = std::function < access::RStatus(std::any, _signature...) >; + + public: + + //every MethodContainer will have a unique-id. + static const std::size_t& getContainerId() { + return m_containerId; + } + + //get the vector holding lambdas as 'const-ref' + static const std::vector& getMethodFunctors() { + return m_methodPtrs; + } + + //get container type as string + template + static const std::string getSignatureStr() { + return (TypeId<_returnType>::toString() + " " + TypeId<_recordType>::toString() + "::(" + TypeId<_signature...>::toString() + ") const"); + } + + private: + + //holds unique-id + static const std::size_t m_containerId; + + //vector holding lambdas + static std::vector m_methodPtrs; + + /* @method: pushBack + @params: pFunctor (lambda containing const-member-function functor call) + pGetIndex (lambda providing index if the functor is already registered) + pUpdate (lambda updating the already registered functors set) + @return: index of newly added or already existing lambda in vector 'm_methodPtrs'. + */ static const std::size_t pushBack(const MethodLambda& pFunctor, + std::function pGetIndex, + std::function pUpdateIndex) + { + //critical section, thread safe. + static std::mutex mtx; + std::lock_guard lock(mtx); + + std::size_t index = pGetIndex(); + if (index == -1) { + index = m_methodPtrs.size(); + pUpdateIndex(index); + m_methodPtrs.push_back(pFunctor); + } + return index; + } + + //friends :) + friend ReflectionBuilder; + friend SetupMethod>; + }; + + template + const std::size_t MethodContainer::m_containerId = g_containerIdCounter.fetch_add(1); + + template + std::vector::MethodLambda> + MethodContainer::m_methodPtrs; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/ReflectionBuilder.h b/ReflectionTemplateLib/detail/inc/ReflectionBuilder.h index 0e8bb5a7..8977b71a 100644 --- a/ReflectionTemplateLib/detail/inc/ReflectionBuilder.h +++ b/ReflectionTemplateLib/detail/inc/ReflectionBuilder.h @@ -4,36 +4,46 @@ namespace rtl { - namespace detail - { - class ReflectionBuilder - { - protected: - - const std::string& m_record; - const std::string& m_function; - const std::string& m_namespace; - - ReflectionBuilder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction); - - template - const access::Function buildConstructor() const; - - template - const access::Function buildCopyConstructor() const; - - template - const access::Function buildConstCopyConstructor() const; - - template - const access::Function buildFunctor(_returnType(*pFunctor)(_signature...)) const; - - template - const access::Function buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...)) const; - - template - const access::Function buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...) const) const; - }; - } + namespace detail + { + /* @class: ReflectionBuilder + * adds the given non-member, static-member 'functor' to the 'FunctionContainer'. + * adds the given const/non-const member, non-static-member 'functor' to the 'MethodContainer'. + * adds the constructor and destructor to 'FunctionContainer'. + */ class ReflectionBuilder + { + protected: + + const std::string& m_record; + const std::string& m_function; + const std::string& m_namespace; + + explicit ReflectionBuilder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + //adds constructor (any overload) to the 'FunctorContainer'. + template + const access::Function buildConstructor() const; + + //adds copy constructor to the 'FunctorContainer'. + template + const access::Function buildCopyConstructor() const; + + //adds const-copy constructor to the 'FunctorContainer'. + template + const access::Function buildConstCopyConstructor() const; + + //adds 'pFunctor' to the 'FunctorContainer'. + template + const access::Function buildFunctor(_returnType(*pFunctor)(_signature...)) const; + + //adds 'pFunctor' to the 'MethodContainer'. + template + const access::Function buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...)) const; + + //adds 'pFunctor' to the 'MethodContainer'. + template + const access::Function buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...) const) const; + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/ReflectionBuilder.hpp b/ReflectionTemplateLib/detail/inc/ReflectionBuilder.hpp index e3a675f3..cf3c968e 100644 --- a/ReflectionTemplateLib/detail/inc/ReflectionBuilder.hpp +++ b/ReflectionTemplateLib/detail/inc/ReflectionBuilder.hpp @@ -6,73 +6,114 @@ namespace rtl { - namespace detail - { - inline ReflectionBuilder::ReflectionBuilder(const std::string& pNamespace, const std::string& pRecord, - const std::string& pFunction) - : m_record(pRecord) - , m_function(pFunction) - , m_namespace(pNamespace) { - } + namespace detail + { + inline ReflectionBuilder::ReflectionBuilder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : m_record(pRecord) + , m_function(pFunction) + , m_namespace(pNamespace) { + } + /* @method: buildFunctor() + @return: 'Function', object associated with the given functor. + @param: 'pFunctor', function pointer with, + * '_returnType' & '_signature...'(auto deduced). + * adds the function pointer in 'FunctorContainer' + * accepts only a non-member or static-member function pointer. + * builds the 'Function' object containing hash-key & meta-data for the given functor. + */ template + inline const access::Function ReflectionBuilder::buildFunctor(_returnType(*pFunctor)(_signature...)) const + { + const std::string& typeStr = detail::TypeId<_signature...>::toString(); + const detail::FunctorId functorId = detail::FunctorContainer<_signature...>::addFunctor(pFunctor); + return access::Function(m_namespace, m_record, m_function, functorId, TypeId<>::None, TypeQ::None); + } - template - inline const access::Function ReflectionBuilder::buildFunctor(_returnType(*pFunctor)(_signature...)) const - { - const std::string& typeStr = detail::TypeId<_signature...>::toString(); - const detail::FunctorId functorId = detail::FunctorContainer<_signature...>::addFunctor(pFunctor); - return access::Function(m_namespace, m_record, m_function, functorId, TypeId<>::None, TypeQ::None); - } + /* @method: buildFunctor() + @return: 'Function', object associated with the given functor. + @param: 'pFunctor', function pointer with, '_recordType' (class/struct), + * '_returnType' & '_signature...'(auto deduced). + * adds the function pointer in 'MethodContainer' + * accepts only a non-static, non-const member function pointer. + * builds the 'Function' object containing hash-key & meta-data for the given functor. + */ template + inline const access::Function ReflectionBuilder::buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...)) const + { + const std::string& typeStr = detail::TypeId<_signature...>::toString(); + const detail::FunctorId functorId = detail::MethodContainer::addFunctor(pFunctor); + return access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::Mute); + } - template - inline const access::Function ReflectionBuilder::buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...)) const - { - const std::string& typeStr = detail::TypeId<_signature...>::toString(); - const detail::FunctorId functorId = detail::MethodContainer::addFunctor(pFunctor); - return access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::Mute); - } + /* @method: buildMethodFunctor() + @return: 'Function', object associated with the given functor. + @param: 'pFunctor', function pointer with, '_recordType' (class/struct), + * '_returnType' & '_signature...'(auto deduced). + * adds the function pointer in 'MethodContainer' + * accepts only a const member function pointer. + * builds the 'Function' object containing hash-key & meta-data for the given functor. + */ template + inline const access::Function ReflectionBuilder::buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...) const) const + { + const std::string& typeStr = detail::TypeId<_signature...>::toString(); + const detail::FunctorId functorId = detail::MethodContainer::addFunctor(pFunctor); + return access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::Const); + } - template - inline const access::Function ReflectionBuilder::buildMethodFunctor(_returnType(_recordType::* pFunctor)(_signature...) const) const - { - const std::string& typeStr = detail::TypeId<_signature...>::toString(); - const detail::FunctorId functorId = detail::MethodContainer::addFunctor(pFunctor); - return access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::Const); - } + /* @method: buildConstructor() + @return: 'Function', object associated with the (specified parametrized) constructor. + @param: '_recordType'(class/struct type) & '_ctorSignature...' (explicitly specified), + * adds the lambda invoking constructor (type-erased) in 'FunctorContainer' + * builds the 'Function' object containing hash-key & meta-data for the constructor. + * also adds the lambda for invoking the destructor and returns its hash-key with the constructor's 'Function'. + */ template + inline const access::Function ReflectionBuilder::buildConstructor() const + { + const detail::FunctorId functorId = detail::FunctorContainer<_ctorSignature...>::template addConstructor<_recordType, _ctorSignature...>(); + const std::string& typeStr = detail::TypeId<_ctorSignature...>::toString(); + const access::Function constructor = access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::None); + //add the destructor's 'FunctorId' to the constructor's functorIds list. + constructor.getFunctorIds().emplace_back(detail::FunctorContainer::addDestructor<_recordType>()); + return constructor; + } - template - inline const access::Function ReflectionBuilder::buildConstructor() const - { - const detail::FunctorId functorId = detail::FunctorContainer<_ctorSignature...>::template addConstructor<_recordType, _ctorSignature...>(); - const std::string& typeStr = detail::TypeId<_ctorSignature...>::toString(); - const access::Function constructor = access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::None); - constructor.getFunctorIds().emplace_back(detail::FunctorContainer::addDestructor<_recordType>()); - return constructor; - } - - template - inline const access::Function ReflectionBuilder::buildCopyConstructor() const - { - const detail::FunctorId functorId = detail::FunctorContainer::addCopyConstructor<_recordType>(); - const std::string& typeStr = detail::TypeId<_ctorSignature...>::toString(); - const access::Function constructor = access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::None); - constructor.getFunctorIds().emplace_back(detail::FunctorContainer::addDestructor<_recordType>()); - return constructor; - } + /* @method: buildCopyConstructor() + @return: 'Function', object associated with the copy constructor. + @param: '_recordType'(class/struct type) & '_ctorSignature...' ('_recordType&', explicitlly specified internally), + * adds the lambda invoking copy constructor (type-erased) in 'FunctorContainer' + * builds the 'Function' object containing hash-key & meta-data for the copy constructor. + * also adds the lambda for invoking the destructor and returns its hash-key with the constructor's 'Function'. + */ template + inline const access::Function ReflectionBuilder::buildCopyConstructor() const + { + const detail::FunctorId functorId = detail::FunctorContainer::addCopyConstructor<_recordType>(); + const std::string& typeStr = detail::TypeId<_ctorSignature...>::toString(); + const access::Function constructor = access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::None); + //add the destructor's 'FunctorId' to the constructor's functorIds list. + constructor.getFunctorIds().emplace_back(detail::FunctorContainer::addDestructor<_recordType>()); + return constructor; + } - template - inline const access::Function ReflectionBuilder::buildConstCopyConstructor() const - { - const detail::FunctorId functorId = detail::FunctorContainer::addConstCopyConstructor<_recordType>(); - const std::string& typeStr = detail::TypeId<_ctorSignature...>::toString(); - const access::Function constructor = access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::None); - constructor.getFunctorIds().emplace_back(detail::FunctorContainer::addDestructor<_recordType>()); - return constructor; - } - } + /* @method: buildConstCopyConstructor() + @return: 'Function', object associated with the copy constructor. + @param: '_recordType'(class/struct type) & '_ctorSignature...' ('const _recordType&', explicitlly specified internally), + * adds the lambda invoking copy constructor (type-erased) taking const-ref in 'FunctorContainer' + * builds the 'Function' object containing hash-key & meta-data for the const-copy constructor. + * also adds the lambda for invoking the destructor and returns its hash-key with the constructor's 'Function'. + */ template + inline const access::Function ReflectionBuilder::buildConstCopyConstructor() const + { + const detail::FunctorId functorId = detail::FunctorContainer::addConstCopyConstructor<_recordType>(); + const std::string& typeStr = detail::TypeId<_ctorSignature...>::toString(); + const access::Function constructor = access::Function(m_namespace, m_record, m_function, functorId, TypeId<_recordType>::get(), TypeQ::None); + //add the destructor's 'FunctorId' to the constructor's functorIds list. + constructor.getFunctorIds().emplace_back(detail::FunctorContainer::addDestructor<_recordType>()); + return constructor; + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupConstructor.h b/ReflectionTemplateLib/detail/inc/SetupConstructor.h index 70e113de..bcd991cc 100644 --- a/ReflectionTemplateLib/detail/inc/SetupConstructor.h +++ b/ReflectionTemplateLib/detail/inc/SetupConstructor.h @@ -4,24 +4,33 @@ namespace rtl { - namespace detail - { - template - class SetupConstructor - { - protected: + namespace detail + { + /* @struct: SetupConstructor + @param: _derivedType ('FunctorContainer') + * creates a constructor-call-wrapped-lambda to perform constructor call. + * adds it to the functor-container, maintains the already added constructor set as well. + * called from 'ReflectionBuilder', as _derivedType member. + */ template + class SetupConstructor + { + protected: - template - static const detail::FunctorId addDestructor(); + //adds the lambda wrapping destructor call to '_derivedType' (FunctorContainer) + template + static const detail::FunctorId addDestructor(); - template - static const detail::FunctorId addConstructor(); + //adds the lambda, wrapping constructor call, recordType(_signature...), to '_derivedType' (FunctorContainer) + template + static const detail::FunctorId addConstructor(); - template - static const detail::FunctorId addCopyConstructor(); + //adds the lambda, wrapping constructor call, _recordType(_recordType&') to '_derivedType' (FunctorContainer) + template + static const detail::FunctorId addCopyConstructor(); - template - static const detail::FunctorId addConstCopyConstructor(); - }; - } + //adds the lambda, wrapping constructor call, _recordType(const _recordType&'), to '_derivedType' (FunctorContainer) + template + static const detail::FunctorId addConstCopyConstructor(); + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupConstructor.hpp b/ReflectionTemplateLib/detail/inc/SetupConstructor.hpp index 459baac9..b63d0833 100644 --- a/ReflectionTemplateLib/detail/inc/SetupConstructor.hpp +++ b/ReflectionTemplateLib/detail/inc/SetupConstructor.hpp @@ -4,113 +4,171 @@ #include "RStatus.h" #include "SetupConstructor.h" -namespace rtl +namespace rtl { - namespace detail - { - template - template - inline const detail::FunctorId SetupConstructor<_derivedType>::addDestructor() - { - static std::size_t dctorIndex = -1; - const auto& updateIndex = [&](const std::size_t& pIndex) { - dctorIndex = pIndex; - }; - const auto& getIndex = [&]()->const std::size_t { - return dctorIndex; - }; - - const auto& functor = [](const std::any& pTarget)->access::RStatus - { - _recordType* object = std::any_cast<_recordType*>(pTarget); - delete object; - return access::RStatus(Error::None); - }; - - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<>::None, TypeId<_recordType>::get(), _derivedType::getContainerId(), - (std::string("~") + _derivedType::template getSignatureStr<_recordType>(true))); - } - - - template - template - inline const detail::FunctorId SetupConstructor<_derivedType>::addConstructor() - { - const auto& recordId = TypeId<_recordType>::get(); - const auto& containerId = _derivedType::getContainerId(); - const auto& hashKey = std::stoull(std::to_string(containerId) + std::to_string(recordId)); - - static std::map ctorSet; - const auto& updateIndex = [&](const std::size_t& pIndex) { - ctorSet.insert(std::make_pair(hashKey, pIndex)); - }; - const auto& getIndex = [&]()->const std::size_t { - const auto& itr = ctorSet.find(hashKey); - return (itr != ctorSet.end() ? itr->second : -1); - }; - - const auto& functor = [=](_signature...params)->access::RStatus - { - _recordType* retObj = new _recordType(params...); - return access::RStatus(std::make_any<_recordType*>(retObj), recordId, TypeQ::Mute); - }; - - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<_recordType>::get(), recordId, containerId, - _derivedType::template getSignatureStr<_recordType>(true)); - } - - - template - template - inline const detail::FunctorId SetupConstructor<_derivedType>::addCopyConstructor() - { - static std::size_t copyCtorIndex = -1; - const auto& updateIndex = [&](const std::size_t& pIndex) { - copyCtorIndex = pIndex; - }; - const auto& getIndex = [&]()->const std::size_t { - return copyCtorIndex; - }; - - const auto& recordId = TypeId<_recordType>::get(); - const auto& functor = [=](const std::any& pOther)->access::RStatus - { - _recordType* srcObj = std::any_cast<_recordType*>(pOther); - _recordType* retObj = new _recordType(*srcObj); - return access::RStatus(std::make_any<_recordType*>(retObj), recordId, TypeQ::Mute); - }; - - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<_recordType>::get(), recordId, _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType>(true)); - } - - - template - template - inline const detail::FunctorId SetupConstructor<_derivedType>::addConstCopyConstructor() - { - static std::size_t constCopyCtorIndex = -1; - const auto& updateIndex = [&](const std::size_t& pIndex) { - constCopyCtorIndex = pIndex; - }; - const auto& getIndex = [&]()->const std::size_t { - return constCopyCtorIndex; - }; - - const auto& recordId = TypeId<_recordType>::get(); - const auto& functor = [=](const std::any& pOther)->access::RStatus - { - const _recordType* srcObj = std::any_cast<_recordType*>(pOther); - _recordType* retObj = new _recordType(*srcObj); - return access::RStatus(std::make_any<_recordType*>(retObj), recordId, TypeQ::Mute); - }; - - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, TypeId<_recordType>::get(), recordId, _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType>(true)); - } - } + namespace detail + { + /* @method: addDestructor() + @param: '_derivedType' (FunctorContainer), '_recordType' (class/struct type) + @return: 'FunctorId' object, a hash-key to lookup the destructor (wrapped in lambda) in the _derivedType's lambda-table. + * adds lambda (destructor-call-wrapped) in '_derivedType' (FunctorContainer). + * maintains a static var for already registered destructor for a particular class/struct type. + * thread safe, this method is uniquely generated for each '_recordType' (class/struct type). + */ template + template + inline const detail::FunctorId SetupConstructor<_derivedType>::addDestructor() + { + //no destructor is registered yet for type '_recordType' if 'dctorIndex' is -1. + static std::size_t dctorIndex = -1; + + //will be called from '_derivedType' if the destructor not already registered. + const auto& updateIndex = [&](const std::size_t& pIndex) { + dctorIndex = pIndex; + }; + + //will be called from '_derivedType' to check if the destructor already registered. + const auto& getIndex = [&]()->const std::size_t { + return dctorIndex; + }; + + //destructor lambda. + const auto& functor = [](const std::any& pTarget)->access::RStatus + { + //cast will definitely succeed, will not throw since the object type is already validated. + _recordType* object = std::any_cast<_recordType*>(pTarget); + delete object; + return access::RStatus(Error::None); + }; + + //add the lambda in 'FunctorContainer'. + const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); + return detail::FunctorId(index, TypeId<>::None, TypeId<_recordType>::get(), _derivedType::getContainerId(), + (std::string("~") + _derivedType::template getSignatureStr<_recordType>(true))); + } + + + /* @method: addConstructor() + @param: '_derivedType' (FunctorContainer), '_recordType' (class/struct), '_signature...' (ctor's args, explicitly specified) + @return: 'FunctorId' object, a hash-key to lookup the lambda in the _derivedType's lambda-table. + * adds lambda (wrapping constructor call) in '_derivedType' (FunctorContainer). + * maintains a static map to check for already registered constructor for a particular class/struct type. + * thread safe, this method is uniquely generated for each '_recordType' (class/struct type). + * adds constructor with any combination of arguments except, copy & const-ref copy constructors. + */ template + template + inline const detail::FunctorId SetupConstructor<_derivedType>::addConstructor() + { + const auto& recordId = TypeId<_recordType>::get(); + const auto& containerId = _derivedType::getContainerId(); + const auto& hashKey = std::stoull(std::to_string(containerId) + std::to_string(recordId)); + + //maintaining a set of already registered constructors. + static std::map ctorSet; + + //will be called from '_derivedType' if the constructor not already registered. + const auto& updateIndex = [&](const std::size_t& pIndex) { + ctorSet.insert(std::make_pair(hashKey, pIndex)); + }; + + //will be called from '_derivedType' to check if the constructor already registered. + const auto& getIndex = [&]()->const std::size_t { + const auto& itr = ctorSet.find(hashKey); + return (itr != ctorSet.end() ? itr->second : -1); + }; + + //lambda containing constructor call. + const auto& functor = [=](_signature...params)->access::RStatus + { + _recordType* retObj = new _recordType(params...); + return access::RStatus(std::make_any<_recordType*>(retObj), recordId, TypeQ::Mute); + }; + + //add the lambda in 'FunctorContainer'. + const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); + return detail::FunctorId(index, TypeId<_recordType>::get(), recordId, containerId, + _derivedType::template getSignatureStr<_recordType>(true)); + } + + + /* @method: addCopyConstructor() + @param: '_derivedType' (FunctorContainer), '_recordType' (class/struct). + @return: 'FunctorId' object, a hash-key to lookup the lambda in the _derivedType's lambda-table. + * adds lambda (wrapping copy-constructor call) in '_derivedType' (FunctorContainer). + * maintains a static map to check for already registered constructor for a particular class/struct type. + * thread safe, this method is uniquely generated for each '_recordType' (class/struct type). + * adds copy constructor with argument '_recordType&'. + */ template + template + inline const detail::FunctorId SetupConstructor<_derivedType>::addCopyConstructor() + { + //no copy-constructor is registered yet for type '_recordType' if 'copyCtorIndex' is -1. + static std::size_t copyCtorIndex = -1; + + //will be called from '_derivedType' if the copy-constructor not already registered. + const auto& updateIndex = [&](const std::size_t& pIndex) { + copyCtorIndex = pIndex; + }; + + //will be called from '_derivedType' to check if the constructor already registered. + const auto& getIndex = [&]()->const std::size_t { + return copyCtorIndex; + }; + + const auto& recordId = TypeId<_recordType>::get(); + //lambda containing constructor call. + const auto& functor = [=](const std::any& pOther)->access::RStatus + { + //cast will definitely succeed, will not throw since the object type is already validated. + _recordType* srcObj = std::any_cast<_recordType*>(pOther); + _recordType* retObj = new _recordType(*srcObj); + return access::RStatus(std::make_any<_recordType*>(retObj), recordId, TypeQ::Mute); + }; + + //add the lambda in 'FunctorContainer'. + const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); + return detail::FunctorId(index, TypeId<_recordType>::get(), recordId, _derivedType::getContainerId(), + _derivedType::template getSignatureStr<_recordType>(true)); + } + + + /* @method: addConstCopyConstructor() + @param: '_derivedType' (FunctorContainer), '_recordType' (class/struct). + @return: 'FunctorId' object, a hash-key to lookup the lambda in the _derivedType's lambda-table. + * adds lambda (wrapping copy-constructor with const-ref call) in '_derivedType' (FunctorContainer). + * maintains a static map to check for already registered constructor for a particular class/struct type. + * thread safe, this method is uniquely generated for each '_recordType' (class/struct type). + * adds copy constructor with argument 'const _recordType&'. + */ template + template + inline const detail::FunctorId SetupConstructor<_derivedType>::addConstCopyConstructor() + { + //no copy constructor with const-ref is registered yet for type '_recordType' if 'constCopyCtorIndex' is -1. + static std::size_t constCopyCtorIndex = -1; + + //will be called from '_derivedType' if the const-ref-copy-constructor not already registered. + const auto& updateIndex = [&](const std::size_t& pIndex) { + constCopyCtorIndex = pIndex; + }; + + //will be called from '_derivedType' to check if the const-ref-copy-constructor already registered. + const auto& getIndex = [&]()->const std::size_t { + return constCopyCtorIndex; + }; + + const auto& recordId = TypeId<_recordType>::get(); + //lambda containing constructor call. + const auto& functor = [=](const std::any& pOther)->access::RStatus + { + //cast will definitely succeed, will not throw since the object type is already validated. + const _recordType* srcObj = std::any_cast<_recordType*>(pOther); + _recordType* retObj = new _recordType(*srcObj); + return access::RStatus(std::make_any<_recordType*>(retObj), recordId, TypeQ::Mute); + }; + + //add the lambda in 'FunctorContainer'. + const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); + return detail::FunctorId(index, TypeId<_recordType>::get(), recordId, _derivedType::getContainerId(), + _derivedType::template getSignatureStr<_recordType>(true)); + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupFunction.h b/ReflectionTemplateLib/detail/inc/SetupFunction.h index 9bdea470..32080305 100644 --- a/ReflectionTemplateLib/detail/inc/SetupFunction.h +++ b/ReflectionTemplateLib/detail/inc/SetupFunction.h @@ -4,15 +4,27 @@ namespace rtl { - namespace detail - { - template - class SetupFunction - { - protected: + namespace detail + { + /* @struct: SetupFunction + @param: _derivedType (type which inherits this class) + * creates a functor-wrapped-lambda to perform call on the registered functor. + * adds it to the functor-container, maintains the already added functor set as well. + * deriving classes is FunctorContainer<...>, which must implement - + - std::size_t& _derived::getContainerId(); + - std::string _derivedType::getSignatureStr(); + - std::size_t& _derived::pushBack(std::function < access::RStatus(_signature...) >, + std::function, + std::function); + * sets up only non-member or static-member-function functors in table. + * called from 'ReflectionBuilder', as _derivedType member. + */ template + class SetupFunction + { + protected: - template - static const detail::FunctorId addFunctor(_returnType(*pFunctor)(_signature...)); - }; - } + template + static const detail::FunctorId addFunctor(_returnType(*pFunctor)(_signature...)); + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupFunction.hpp b/ReflectionTemplateLib/detail/inc/SetupFunction.hpp index c4fe955a..ad6aee7b 100644 --- a/ReflectionTemplateLib/detail/inc/SetupFunction.hpp +++ b/ReflectionTemplateLib/detail/inc/SetupFunction.hpp @@ -4,42 +4,77 @@ namespace rtl { - namespace detail - { - template - template - inline const detail::FunctorId SetupFunction<_derivedType>::addFunctor(_returnType(*pFunctor)(_signature...)) - { - static std::vector> functorSet; - const auto& updateIndex = [&](const std::size_t& pIndex) { - functorSet.emplace_back(pFunctor, pIndex); - }; - const auto& getIndex = [&]()->const std::size_t { - for (const auto& fptr : functorSet) { - if (fptr.first == pFunctor) { - return fptr.second; - } - } - return -1; - }; - - const auto& retTypeId = TypeId<_returnType>::get(); - const auto functor = [=](_signature...params)->access::RStatus - { - if constexpr (std::is_same_v<_returnType, void>) { - (*pFunctor)(params...); - return access::RStatus(Error::None); - } - else { - const _returnType& retObj = (*pFunctor)(params...); - const TypeQ& qualifier = std::is_const<_returnType>::value ? TypeQ::Const : TypeQ::Mute; - return access::RStatus(std::make_any<_returnType>(retObj), retTypeId, qualifier); - } - }; - - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, retTypeId, TypeId<>::None, _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_returnType>()); - } - } + namespace detail + { + /* @method: addFunctor(). + @param: 'pFuntor' (a non-member or static-member function pointer). + '_derivedType' : class deriving this class ('FunctionContainer<...>'). + '_returnType' : return type deduced from 'pFunctor'. + '_signature...' : function signature deduced from 'pFunctor'. + @return: 'FunctorId' object, a hash-key to lookup the functor in the _derivedType's lambda-table. + * adds functor in _derivedType ('FunctionContainer<...>') and maintains functorSet of already registered functors. + * thread safe, multiple functors can be registered simultaneously. + */ template + template + inline const detail::FunctorId SetupFunction<_derivedType>::addFunctor(_returnType(*pFunctor)(_signature...)) + { + + /* set of already registered functors. (static life time). + used std::vector, since std::set/map are not designed for function pointers + */ static std::vector> functorSet; + + /* adds the generated functor index to the 'functorSet'. (thread safe). + called from '_derivedType' ('FunctorContainer') + */ const auto& updateIndex = [&](const std::size_t& pIndex) + { + functorSet.emplace_back(pFunctor, pIndex); + }; + + /* checks if the 'pFunctor' is already present in 'functorSet'. (thread safe). + called from '_derivedType' ('FunctorContainer') + */ const auto& getIndex = [&]()->const std::size_t + { + //linear search, efficient for small set. + for (const auto& fptr : functorSet) { + if (fptr.first == pFunctor) { + //functor already registered, return its 'index'. + return fptr.second; + } + } + //functor is not already registered, return '-1'. + return -1; + }; + + //generate a type-id of '_returnType'. + const auto& retTypeId = TypeId<_returnType>::get(); + + /* a variable arguments lambda, which finally calls the 'pFunctor' with 'params...'. + this is stored in _derivedType's (FunctorContainer) vector holding lambda's. + */ const auto functor = [=](_signature...params)->access::RStatus + { + //if functor does not returns anything, this 'if' block is retained and else block is omitted by compiler. + if constexpr (std::is_same_v<_returnType, void>) { + + //call will definitely be successful, since the signature type has alrady been validated. + (*pFunctor)(params...); + return access::RStatus(Error::None); + } + //if functor returns value, this 'else' block is retained and 'if' block is omitted by compiler. + else { + //call will definitely be successful, since the signature type has alrady been validated. + const _returnType& retObj = (*pFunctor)(params...); + const TypeQ& qualifier = std::is_const<_returnType>::value ? TypeQ::Const : TypeQ::Mute; + //return 'RStatus' with return value wrapped in it as std::any. + return access::RStatus(std::make_any<_returnType>(retObj), retTypeId, qualifier); + } + }; + + //finally add the lambda 'functor' in 'FunctorContainer' lambda vector and get the index. + const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); + + //construct the hash-key 'FunctorId' and return. + return detail::FunctorId(index, retTypeId, TypeId<>::None, _derivedType::getContainerId(), + _derivedType::template getSignatureStr<_returnType>()); + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/SetupMethod.h b/ReflectionTemplateLib/detail/inc/SetupMethod.h index 4f8f81d2..88fd55c0 100644 --- a/ReflectionTemplateLib/detail/inc/SetupMethod.h +++ b/ReflectionTemplateLib/detail/inc/SetupMethod.h @@ -6,7 +6,20 @@ namespace rtl { namespace detail { - template + /* @struct: SetupMethod + @param: _derivedType (type which inherits this class) + * creates a lambda to perform call on the registered functor. + * adds it to the functor-container, maintains the already added functor set as well. + * deriving classes is MethodContainer & + MethodContainer, which must implement - + - std::size_t& _derived::getContainerId(); + - std::string _derivedType::getSignatureStr(); + - std::size_t& _derived::pushBack(std::function < access::RStatus(_signature...) >, + std::function, + std::function); + * sets up only non-static-member-function functors in lambda table. + * called from 'ReflectionBuilder', as _derivedType member. + */ template class SetupMethod { protected: diff --git a/ReflectionTemplateLib/detail/inc/SetupMethod.hpp b/ReflectionTemplateLib/detail/inc/SetupMethod.hpp index 09788516..afc1f219 100644 --- a/ReflectionTemplateLib/detail/inc/SetupMethod.hpp +++ b/ReflectionTemplateLib/detail/inc/SetupMethod.hpp @@ -6,83 +6,152 @@ namespace rtl { - namespace detail - { - template - template - inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...)) - { - static std::vector> functorSet; - const auto& updateIndex = [&](const std::size_t& pIndex) { - functorSet.emplace_back(pFunctor, pIndex); - }; - const auto& getIndex = [&]()->const std::size_t { - for (const auto& fptr : functorSet) { - if (fptr.first == pFunctor) { - return fptr.second; - } - } - return -1; - }; + namespace detail + { + /* @method: addFunctor(). + @param: 'pFuntor' (a non-const, non-static-member function pointer). + '_derivedType' : class deriving this class ('MethodContainer'). + '_recordType' : the owner 'class/stuct' type of the functor. + '_returnType' : return type deduced from 'pFunctor'. + '_signature...' : function signature deduced from 'pFunctor'. + @return: 'FunctorId' object, a hash-key to lookup the lambda (functor-wrapped) in the _derivedType's lambda-table. + * adds lambda (functor-wrapped) in '_derivedType' (MethodContainer) and maintains functorSet. + * thread safe, multiple functors can be registered simultaneously. + */ template + template + inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...)) + { + /* set of already registered functors. (static life time). + used std::vector, efficient for small sets. std::set/map will be overhead. + */ static std::vector> functorSet; - const std::size_t retTypeId = TypeId<_retType>::get(); - const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus - { - _recordType* target = std::any_cast<_recordType*>(pTargetObj); - - if constexpr (std::is_same_v<_retType, void>) { - (target->*pFunctor)(params...); - return access::RStatus(Error::None); - } - else { - const _retType& retObj = (target->*pFunctor)(params...); - const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; - return access::RStatus(std::make_any<_retType>(retObj), retTypeId, qualifier); - } - }; + /* adds the generated functor index to the 'functorSet'. (thread safe). + called from '_derivedType' (MethodContainer) + */ const auto& updateIndex = [&](const std::size_t& pIndex) { + functorSet.emplace_back(pFunctor, pIndex); + }; - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, retTypeId, TypeId<_recordType>::get(), _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType, _retType>()); - } + /* checks if the 'pFunctor' is already present in 'functorSet'. (thread safe). + called from '_derivedType' ('FunctorContainer') + */ const auto& getIndex = [&]()->const std::size_t + { + //linear search, efficient for small set. + for (const auto& fptr : functorSet) { + if (fptr.first == pFunctor) { + //functor already registered, return its 'index'. + return fptr.second; + } + } + //functor is not already registered, return '-1'. + return -1; + }; + //generate a type-id of '_returnType'. + const std::size_t retTypeId = TypeId<_retType>::get(); + + /* a variable arguments lambda, which finally calls the 'pFunctor' with 'params...'. + this is stored in _derivedType's (MethodContainer) vector holding lambda's. + */ const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus + { + //cast would not fail, since the type has already been validated. + _recordType* target = std::any_cast<_recordType*>(pTargetObj); + + //if functor does not returns anything, this 'if' block is retained and else block is omitted by compiler. + if constexpr (std::is_same_v<_retType, void>) { + //call will definitely be successful, since the object type, signature type has already been validated. + (target->*pFunctor)(params...); + return access::RStatus(Error::None); + } + //if functor returns value, this 'else' block is retained and 'if' block is omitted by compiler. + else { + + //call will definitely be successful, since the object type, signature type has already been validated. + const _retType& retObj = (target->*pFunctor)(params...); + const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; + + //return 'RStatus' with return value wrapped in it as std::any. + return access::RStatus(std::make_any<_retType>(retObj), retTypeId, qualifier); + } + }; + + //finally add the lambda 'functor' in 'MethodContainer' lambda vector and get the index. + const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); + + //construct the hash-key 'FunctorId' and return. + return detail::FunctorId(index, retTypeId, TypeId<_recordType>::get(), _derivedType::getContainerId(), + _derivedType::template getSignatureStr<_recordType, _retType>()); + } - template - template - inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...) const) - { - static std::vector> functorSet; - const auto& updateIndex = [&](const std::size_t& pIndex) { - functorSet.emplace_back(pFunctor, pIndex); - }; - const auto& getIndex = [&]()->const std::size_t { - for (const auto& fptr : functorSet) { - if (fptr.first == pFunctor) { - return fptr.second; - } - } - return -1; - }; - const std::size_t retTypeId = TypeId<_retType>::get(); - const std::size_t constRetTypeId = TypeId::get(); - const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus - { - _recordType* target = std::any_cast<_recordType*>(pTargetObj); - if constexpr (std::is_same_v<_retType, void>) { - ((static_cast(target))->*pFunctor)(params...); - return access::RStatus(Error::None); - } - else { - const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; - const _retType& retObj = ((static_cast(target))->*pFunctor)(params...); - return access::RStatus(std::make_any<_retType>(retObj), retTypeId, constRetTypeId, qualifier); - } + /* @method: addFunctor(). + @param: 'pFuntor' (a const, non-static-member function pointer). + '_derivedType' : class deriving this class ('MethodContainer'). + '_recordType' : the owner 'class/stuct' type of the functor. + '_returnType' : return type deduced from 'pFunctor'. + '_signature...' : function signature deduced from 'pFunctor'. + @return: 'FunctorId' object, a hash-key to lookup the lambda (containing functor) in the _derivedType's lambda table. + * adds lambda (containing functor) in '_derivedType' (MethodContainer) and maintains a functorSet. + * thread safe, multiple functors can be registered simultaneously. + */ template + template + inline const detail::FunctorId SetupMethod<_derivedType>::addFunctor(_retType(_recordType::* pFunctor)(_signature...) const) + { + /* set of already registered functors. (static life time). + used std::vector, efficient for small sets. std::set/map will be overhead. + */ static std::vector> functorSet; + const auto& updateIndex = [&](const std::size_t& pIndex) { + functorSet.emplace_back(pFunctor, pIndex); }; - const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); - return detail::FunctorId(index, retTypeId, TypeId<_recordType>::get(), _derivedType::getContainerId(), - _derivedType::template getSignatureStr<_recordType, _retType>()); - } - } + /* adds the generated functor index to the 'functorSet'. (thread safe). + called from '_derivedType' (MethodContainer) + */ const auto& getIndex = [&]()->const std::size_t + { + //linear search, efficient for small set. + for (const auto& fptr : functorSet) { + if (fptr.first == pFunctor) { + //functor already registered, return its 'index'. + return fptr.second; + } + } + //functor is not already registered, return '-1'. + return -1; + }; + + //generate a type-id of '_retType'. + const std::size_t retTypeId = TypeId<_retType>::get(); + + /* a variable arguments lambda, which finally calls the 'pFunctor' with 'params...'. + this is stored in _derivedType's (MethodContainer) vector holding lambda's. + */ const auto functor = [=](const std::any& pTargetObj, _signature...params)->access::RStatus + { + //cast would not fail, since the type has already been validated. + _recordType* target = std::any_cast<_recordType*>(pTargetObj); + + //if functor does not returns anything, this 'if' block is retained and else block is omitted by compiler. + if constexpr (std::is_same_v<_retType, void>) { + + //call will definitely be successful, since the object type, signature type has already been validated. + ((static_cast(target))->*pFunctor)(params...); + return access::RStatus(Error::None); + } + else { + const TypeQ& qualifier = std::is_const<_retType>::value ? TypeQ::Const : TypeQ::Mute; + + //call will definitely be successful, since the object type, signature type has already been validated. + const _retType& retObj = ((static_cast(target))->*pFunctor)(params...); + + //return 'RStatus' with return value wrapped in it as std::any. + return access::RStatus(std::make_any<_retType>(retObj), retTypeId, qualifier); + } + }; + + //finally add the lambda 'functor' in 'MethodContainer' lambda vector and get the index. + const std::size_t& index = _derivedType::pushBack(functor, getIndex, updateIndex); + + //construct the hash-key 'FunctorId' and return. + return detail::FunctorId(index, retTypeId, TypeId<_recordType>::get(), _derivedType::getContainerId(), + _derivedType::template getSignatureStr<_recordType, _retType>()); + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/TypeId.h b/ReflectionTemplateLib/detail/inc/TypeId.h index b8092c03..12e4833e 100644 --- a/ReflectionTemplateLib/detail/inc/TypeId.h +++ b/ReflectionTemplateLib/detail/inc/TypeId.h @@ -5,55 +5,65 @@ namespace rtl { - namespace detail - { - template - struct TypeId; - - template - struct TypeId<_type> - { - using HEAD = _type; - - static constexpr const std::size_t None = 0; - - static const std::size_t get() { - return m_typeId; - } - - static const std::string toString() - { - if (std::is_same<_type, void>::value) { - return std::string("void"); - } - if (std::is_same<_type, std::string>::value) { - return std::string("std::string"); - } - if (!std::is_same<_type, std::nullptr_t>::value) { - return std::string(typeid(_type).name()); - } - else return std::string(); - } - - private: - static const std::size_t m_typeId; - }; - - - template - struct TypeId - { - using HEAD = _first; - using TAIL = TypeId<_rest...>; - - static const std::string toString() { - - const std::string& tailStr = TAIL::toString(); - if (std::is_same::value) { - return std::string("std::string") + ", " + tailStr; - } - return (std::string(typeid(HEAD).name()) + ", " + tailStr); - } - }; - } + namespace detail + { + //class to generate unique type-id for a type or combination of types. + template + struct TypeId; + + //class to generate unique type-id a type. + template + struct TypeId<_type> + { + //represents '_type' or 'std::nullptr_t' for TypeId<> (empty). + using HEAD = _type; + + //'0' represents no type. + static constexpr const std::size_t None = 0; + + static const std::size_t get() { + return m_typeId; + } + + //returns the type-list as string. + static const std::string toString() + { + if constexpr (std::is_same_v<_type, void>) { + return std::string("void"); + } + if constexpr (std::is_same_v<_type, std::string>) { + return std::string("std::string"); + } + if constexpr (!std::is_same_v<_type, std::nullptr_t>) { + return std::string(typeid(_type).name()); + } + else return std::string(); + } + + private: + static const std::size_t m_typeId; + }; + + + //class to generate unique type-id for a combination of types. + template + struct TypeId + { + //represents the first type in given list. + using HEAD = _first; + + //represents a new list created excluding '_first'. + using TAIL = TypeId<_rest...>; + + //returns the type-list as string. + static const std::string toString() + { + const std::string& tailStr = TAIL::toString(); + if (std::is_same::value) { + return std::string("std::string") + ", " + tailStr; + } + return (std::string(typeid(HEAD).name()) + ", " + tailStr); + } + }; + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/inc/TypeId.hpp b/ReflectionTemplateLib/detail/inc/TypeId.hpp index 5debdee6..d187dc46 100644 --- a/ReflectionTemplateLib/detail/inc/TypeId.hpp +++ b/ReflectionTemplateLib/detail/inc/TypeId.hpp @@ -10,6 +10,7 @@ namespace rtl { { extern std::atomic g_typeIdCounter; + //statically initialize a unique-id. template const std::size_t TypeId<_type>::m_typeId = g_typeIdCounter.fetch_add(1); } diff --git a/ReflectionTemplateLib/detail/src/FunctorId.cpp b/ReflectionTemplateLib/detail/src/FunctorId.cpp index 06bb9627..72ecc1f3 100644 --- a/ReflectionTemplateLib/detail/src/FunctorId.cpp +++ b/ReflectionTemplateLib/detail/src/FunctorId.cpp @@ -13,7 +13,7 @@ namespace rtl - whether it is const or non-const - class/struct type 'm_containerId' will be same for functors with same above attributes. - * every functor will have a distinct index in the functor table. + * every functor will have a distinct index in the functor-wrapped-lambda-table. * so, combination of m_containerId & m_index is unique for every functor. */ std::size_t FunctorId::getHashCode() const { diff --git a/ReflectionTemplateLib/detail/src/TypeIdInitializer.cpp b/ReflectionTemplateLib/detail/src/TypeIdInitializer.cpp index e25a1054..1040c84c 100644 --- a/ReflectionTemplateLib/detail/src/TypeIdInitializer.cpp +++ b/ReflectionTemplateLib/detail/src/TypeIdInitializer.cpp @@ -8,7 +8,10 @@ namespace rtl { namespace detail { + //type id counter, statically initializes a unique-id to TypeId<...>. std::atomic g_typeIdCounter = TypeId<>::None + 1; + + //type id counter, statically initializes a unique-id to FunctorContainer<...> and MethodContainer<...>. std::atomic g_containerIdCounter = TypeId<>::None + 1; } } \ No newline at end of file