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..f6d80fd7 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,48 @@ 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) + 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) + { { CxxMirror& cxxMirror = MyReflection::instance(); @@ -97,12 +132,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 +160,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 +192,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 +221,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/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 adcb6d02..99d015d0 100644 --- a/CxxTypeRegistration/src/MyReflection.cpp +++ b/CxxTypeRegistration/src/MyReflection.cpp @@ -26,63 +26,66 @@ 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. - 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_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'. + 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..81b49cde 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 '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: + + //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/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..9bf7f023 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 the 'lambda' in functor-container, 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 'lambda' in functor-container, 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..387b4a6a 100644 --- a/ReflectionTemplateLib/access/inc/Instance.h +++ b/ReflectionTemplateLib/access/inc/Instance.h @@ -9,41 +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; - const std::size_t m_constTypeId; + //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..f3610c6e 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. + explicit Method(const Function& pFunction); + + //private ctor, called by 'Record' class. + explicit 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..40ea066e 100644 --- a/ReflectionTemplateLib/access/inc/Method.hpp +++ b/ReflectionTemplateLib/access/inc/Method.hpp @@ -3,133 +3,182 @@ 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 - { - 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); - } - } + //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 + { + /* @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); + } + + + /* @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); + } + + + /* @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 and call. + return invokeConst(pTarget, params...); + } + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/access/inc/RStatus.h b/ReflectionTemplateLib/access/inc/RStatus.h index 0017b585..d61d8be9 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, 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) + 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.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/inc/Record.hpp b/ReflectionTemplateLib/access/inc/Record.hpp index 60a20e74..42a47fec 100644 --- a/ReflectionTemplateLib/access/inc/Record.hpp +++ b/ReflectionTemplateLib/access/inc/Record.hpp @@ -7,24 +7,46 @@ 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 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()) { + + //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 '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 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()); + } + 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 6d61b3ae..26d9db53 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/Function.cpp b/ReflectionTemplateLib/access/src/Function.cpp index fae21ad8..0402d4ef 100644 --- a/ReflectionTemplateLib/access/src/Function.cpp +++ b/ReflectionTemplateLib/access/src/Function.cpp @@ -1,81 +1,84 @@ -#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 + { + /* @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. + */ 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_record(pRecord) + , m_function(pFunction) + , m_namespace(pNamespace) + , m_functorIds({ 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 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_record(pOther.m_record) + , m_function(pFunctorName) + , m_namespace(pOther.m_namespace) + , m_functorIds({ pFunctorId }) { + } + + + /* @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, 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 '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 { - } - - - 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, efficient for small set of elements. + for (const auto& functorId : m_functorIds) { + if (functorId.getSignatureId() == otherFuncSignId) { + return; //ignore and return since 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..649c9e9d 100644 --- a/ReflectionTemplateLib/access/src/Instance.cpp +++ b/ReflectionTemplateLib/access/src/Instance.cpp @@ -8,61 +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) - , m_constTypeId(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) { - } - - - 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) - { - 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/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/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 0c773576..4df8986d 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 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. + 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 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. + 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 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. + 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/Builder.h b/ReflectionTemplateLib/builder/inc/Builder.h index ddf011d0..88818597 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.h +++ b/ReflectionTemplateLib/builder/inc/Builder.h @@ -5,123 +5,178 @@ 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; - }; - - - 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; - }; - } - - - 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() const; - - template - constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; - }; - } + namespace builder + { + /* @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; + } + + + namespace builder + { + /* @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 + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(*pFunctor)()) const; + }; + + + /* @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 + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(*pFunctor)(_signature...)) const; + }; + + + /* @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 + { + 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 + { + /* @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 + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)() const) const; + }; + + + /* @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 + { + 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; + }; + + + /* @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 + { + 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 + { + /* @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 + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)()) const; + }; + + + /* @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 + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build(_returnType(_recordType::* pFunctor)(_signature...)) const; + }; + + + /* @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 + { + Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction); + + template + constexpr const access::Function build() 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 a92b35ca..46bba871 100644 --- a/ReflectionTemplateLib/builder/inc/Builder.hpp +++ b/ReflectionTemplateLib/builder/inc/Builder.hpp @@ -4,167 +4,228 @@ namespace rtl { - namespace builder + namespace builder + { + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } + + /* @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. + */ 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) { - } - - template - inline constexpr const access::Function Builder::build(_returnType(*pFunctor)(_signature...)) const - { - return buildFunctor(pFunctor); - } - } + inline Builder::Builder(const std::string& pNamespace, const std::string& pRecord, + const std::string& pFunction) + : ReflectionBuilder(pNamespace, pRecord, pFunction) { + } + + /* @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. + */ 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) { + } + + + /* @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. + */ 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) { + } + + /* @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. + */ 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) { + } + + /* @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. + */ template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)() 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(_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) { - } - - 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) { - } - - 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 - { - 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(_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() const - { - 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...>(); - } - } - - - 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) { - } - - 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) { + } + + /* @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. + */ 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) { + } + + + /* @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. + * calling with zero template params will build the default constructor ie, 'RecordBuilder<_recordType>::constructor()' + */ template + 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...>(); + } + } + + + /* @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. + */ 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) { + } + + + /* @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. + */ 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) { + } - template - template - inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const - { - return buildMethodFunctor(pFunctor); - } - } + /* @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. + */ template + template + inline constexpr const access::Function Builder::build(_returnType(_recordType::* pFunctor)(_signature...)) const + { + return buildMethodFunctor(pFunctor); + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h index 190ed279..c29db0ee 100644 --- a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h +++ b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.h @@ -4,23 +4,39 @@ namespace rtl { - namespace builder - { - template - class ConstructorBuilder - { - const std::string& m_record; - const std::string& m_namespace; - const FunctorType m_ctorType; + namespace builder + { + /* @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; - ConstructorBuilder() = delete; + //given name of the namespace. + const std::string& m_namespace; - public: + /* 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(const std::string& pNamespace, const std::string& pRecord, - const FunctorType& pCtorType); + ConstructorBuilder() = delete; - inline constexpr const access::Function build() const; + public: + + ConstructorBuilder(const std::string& pNamespace, const std::string& pRecord, + const FunctorType& pCtorType); + + 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 d2b9ae7e..e6608590 100644 --- a/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp +++ b/ReflectionTemplateLib/builder/inc/ConstructorBuilder.hpp @@ -6,37 +6,30 @@ 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) - { - } + 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...>(); - } - } - } - } + /* @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 + { + 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 dcc1d14e..21970f2c 100644 --- a/ReflectionTemplateLib/builder/inc/RecordBuilder.h +++ b/ReflectionTemplateLib/builder/inc/RecordBuilder.h @@ -4,38 +4,41 @@ 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; + /* @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; + 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 1e4d401d..5de80103 100644 --- a/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp +++ b/ReflectionTemplateLib/builder/inc/RecordBuilder.hpp @@ -5,73 +5,129 @@ 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 - { - 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); - } - } + namespace builder + { + template + inline RecordBuilder<_recordType>::RecordBuilder(const std::string& pNamespace, const std::string& pRecord) + : m_record(pRecord) + , m_namespace(pNamespace) { + } + + + /* @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); + } + + + /* @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 + { + return Builder(m_namespace, m_record, pFunction); + } + + + /* @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); + } + + + /* @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); + } + + + /* @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 + { + return Builder(m_namespace, m_record, pFunction); + } + + + /* @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 + { + 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..341ca0c4 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. + std::string m_record; - public: + //name of the namespace being registered. + 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..d1147033 100644 --- a/ReflectionTemplateLib/builder/inc/Reflect.hpp +++ b/ReflectionTemplateLib/builder/inc/Reflect.hpp @@ -6,39 +6,69 @@ 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 default name: NAMESPACE_GLOBAL. + , m_namespace(NAMESPACE_GLOBAL) { + } - inline Reflect& Reflect::nameSpace(const std::string& pNamespace) - { - m_namespace = pNamespace; - return *this; - } + /* @function: nameSpace() + @param: std::string, name of the 'namespace' as string. + @return: '*this', Reflect. + * 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; + return *this; + } - template<> - inline const Builder Reflect::function(const std::string& pFunction) - { - return Builder(m_namespace, m_record, pFunction); - } + /* @function: function() + @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. + * 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) + @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. + * 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) + @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 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/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/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/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 2e2af572..b1893fde 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 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/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 43ed376a..88fd55c0 100644 --- a/ReflectionTemplateLib/detail/inc/SetupMethod.h +++ b/ReflectionTemplateLib/detail/inc/SetupMethod.h @@ -4,10 +4,23 @@ namespace rtl { - namespace detail + namespace detail { - template - class SetupMethod + /* @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 ff8c2ace..afc1f219 100644 --- a/ReflectionTemplateLib/detail/inc/SetupMethod.hpp +++ b/ReflectionTemplateLib/detail/inc/SetupMethod.hpp @@ -4,85 +4,154 @@ #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...)) - { - 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/CxxReflection.cpp b/ReflectionTemplateLib/detail/src/CxxReflection.cpp index d6092093..536e698e 100644 --- a/ReflectionTemplateLib/detail/src/CxxReflection.cpp +++ b/ReflectionTemplateLib/detail/src/CxxReflection.cpp @@ -6,93 +6,122 @@ 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 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) + { + 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 than 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 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 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()) { + const auto& funcMapItr = m_nsFunctionsMap.emplace(nameSpace, FunctionMap()); + addFunction(funcMapItr.first->second, pFunction); + } + else { + 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()) { + const auto& recordMapItr = m_nsRecordsMap.emplace(nameSpace, RecordMap()); + addRecord(recordMapItr.first->second, pFunction); + } + else { + addRecord(itr->second, pFunction); + } + } + } + } } \ No newline at end of file diff --git a/ReflectionTemplateLib/detail/src/FunctorId.cpp b/ReflectionTemplateLib/detail/src/FunctorId.cpp index f544950f..72ecc1f3 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-wrapped-lambda-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 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