diff --git a/include/reflection-cpp/reflection.hpp b/include/reflection-cpp/reflection.hpp index ae7a240..00265f2 100644 --- a/include/reflection-cpp/reflection.hpp +++ b/include/reflection-cpp/reflection.hpp @@ -522,7 +522,7 @@ inline constexpr auto MemberNameOf = []() constexpr { }(); template -constexpr auto TypeName = [] { +constexpr auto TypeNameOf = [] { constexpr std::string_view name = detail::MangledName(); constexpr auto begin = name.find(detail::reflect_type::end); constexpr auto tmp = name.substr(0, begin); @@ -589,7 +589,7 @@ namespace detail consteval std::string_view func_name_msvc() { std::string_view str = REFLECTION_PRETTY_FUNCTION; - str = str.substr(str.rfind(TypeName) + TypeName.size()); + str = str.substr(str.rfind(TypeNameOf) + TypeNameOf.size()); str = str.substr(str.find("::") + 2); return str.substr(0, str.find('(')); } @@ -604,11 +604,9 @@ namespace detail template constexpr void enumerate_types(F&& f) { - [&f](std::index_sequence) - { + [&f](std::index_sequence) { (f.template operator()(), ...); - } - (std::index_sequence_for {}); + }(std::index_sequence_for {}); } template @@ -627,67 +625,71 @@ constexpr void template_for(F&& f) { using t = std::common_type_t; - [&f](std::integer_sequence) - { + [&f](std::integer_sequence) { detail::for_values<(B + Xs)...>(f); - } - (std::make_integer_sequence {}); + }(std::make_integer_sequence {}); } template constexpr void template_for(F&& f) { using t = typename ElementMask::value_type; - [&f](std::integer_sequence) - { + [&f](std::integer_sequence) { Reflection::detail::for_values<(Xs)...>(f); - } - (ElementMask {}); + }(ElementMask {}); } -template - requires(std::is_member_pointer_v) -consteval std::string_view GetName() +namespace detail { -#if defined(_MSC_VER) && !defined(__clang__) - if constexpr (std::is_member_object_pointer_v) - { - using T = detail::remove_member_pointer>::type; - constexpr auto p = P; - return detail::get_name_msvc.*p)>(); - } - else + + template + requires(std::is_member_pointer_v) + consteval std::string_view GetName() { - using T = detail::remove_member_pointer>::type; - return detail::func_name_msvc(); - } +#if defined(_MSC_VER) && !defined(__clang__) + if constexpr (std::is_member_object_pointer_v) + { + using T = detail::remove_member_pointer>::type; + constexpr auto p = P; + return detail::get_name_msvc.*p)>(); + } + else + { + using T = detail::remove_member_pointer>::type; + return detail::func_name_msvc(); + } #else - // TODO: Use std::source_location when deprecating clang 14 - // std::string_view str = std::source_location::current().function_name(); - std::string_view str = REFLECTION_PRETTY_FUNCTION; - str = str.substr(str.find('&') + 1); - str = str.substr(0, str.find(detail::pretty_function_tail)); - return str.substr(str.rfind("::") + 2); + // TODO: Use std::source_location when deprecating clang 14 + // std::string_view str = std::source_location::current().function_name(); + std::string_view str = REFLECTION_PRETTY_FUNCTION; + str = str.substr(str.find('&') + 1); + str = str.substr(0, str.find(detail::pretty_function_tail)); + return str.substr(str.rfind("::") + 2); #endif -} + } -template - requires(std::is_enum_v) -consteval auto GetName() -{ + template + requires(std::is_enum_v) + consteval auto GetName() + { #if defined(_MSC_VER) && !defined(__clang__) - std::string_view str = REFLECTION_PRETTY_FUNCTION; - str = str.substr(str.rfind("::") + 2); - str = str.substr(0, str.find('>')); - return str.substr(str.find('<') + 1); + std::string_view str = REFLECTION_PRETTY_FUNCTION; + str = str.substr(str.rfind("::") + 2); + str = str.substr(0, str.find('>')); + return str.substr(str.find('<') + 1); #else - constexpr auto MarkerStart = std::string_view { "E = " }; - std::string_view str = REFLECTION_PRETTY_FUNCTION; - str = str.substr(str.rfind(MarkerStart) + MarkerStart.size()); - str = str.substr(0, str.find(']')); - return str; + constexpr auto MarkerStart = std::string_view { "E = " }; + std::string_view str = REFLECTION_PRETTY_FUNCTION; + str = str.substr(str.rfind(MarkerStart) + MarkerStart.size()); + str = str.substr(0, str.find(']')); + return str; #endif -} + } +} // namespace detail + +/// Gets the name of a member or function pointer +template +constexpr std::string_view NameOf = detail::GetName(); /// Calls a callable on members of an object specified with ElementMask sequence with the index of the member as the /// first argument. and the member's default-constructed value as the second argument. @@ -730,8 +732,7 @@ template requires std::same_as>> void CallOnMembers(Object& object, Callable&& callable) { - EnumerateMembers(object, - [&](T&& value) { callable(MemberNameOf, value); }); + EnumerateMembers(object, [&](T&& value) { callable(MemberNameOf, value); }); } /// Folds over the members of a type without an object of it. diff --git a/test-reflection-cpp.cpp b/test-reflection-cpp.cpp index 11d35f4..385f64b 100644 --- a/test-reflection-cpp.cpp +++ b/test-reflection-cpp.cpp @@ -35,18 +35,25 @@ struct SingleValueRecord int value; }; -TEST_CASE("GetName", "[reflection]") +TEST_CASE("TypeNameOf", "[reflection]") { - auto const enumValue = Reflection::GetName(); + CHECK(Reflection::TypeNameOf == "int"); + CHECK(Reflection::TypeNameOf == "Person"); + CHECK(Reflection::TypeNameOf> == "std::optional"); +} + +TEST_CASE("NameOf", "[reflection]") +{ + auto const enumValue = Reflection::NameOf; CHECK(enumValue == "Red"); - auto const enumValue2 = Reflection::GetName(); + auto const enumValue2 = Reflection::NameOf; CHECK(enumValue2 == "Green"); - auto const memberName1 = Reflection::GetName<&Person::email>(); + auto const memberName1 = Reflection::NameOf<&Person::email>; CHECK(memberName1 == "email"); - auto const singleValueField = Reflection::GetName<&SingleValueRecord::value>(); + auto const singleValueField = Reflection::NameOf<&SingleValueRecord::value>; CHECK(singleValueField == "value"); }