diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..747762f --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,26 @@ +# Roadmap + +## Backlog + +- instance mapper +- type conversions +- dynamic binds listener +- static binds listener +- dynamic type visitor +- type names by [nameof](https://github.com/Neargye/nameof) +- non-linear search of methods/functions/... +- register base types by `META_HPP_ENABLE_POLY_INFO` +- distinguish between function types and function pointer types +- add the library version to sources +- fix all includes to work with the library more flexible +- build and test on CI with additional flags like no-exception and no-rtti +- `try_invoke`/`is_invocable` should return error codes +- conan package config +- test and support shared libraries +- add `for_each_type` for specific kind of types + +## Thoughts + +- should `uvalue` dereference operators return `reference_wrapper`? +- `array_view`/`pointer_view` instead `unmap`/`operator[]`/`operator*`? +- can we add move-only uvalue analog to return move-only values? diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index d5b2b19..6a105cc 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -1798,10 +1798,10 @@ namespace meta_hpp using metadata_map = std::map>; using typedef_map = std::map>; + using any_type_list = std::vector; using class_list = std::vector; using enum_list = std::vector; - using any_type_list = std::vector; using argument_list = std::vector; using constructor_list = std::vector; using destructor_list = std::vector; @@ -2457,21 +2457,43 @@ namespace meta_hpp public: type_id() = default; - explicit type_id(std::uintptr_t id) - : id_{id} {} + [[nodiscard]] bool is_valid() const noexcept { + return data_ != nullptr; + } + + [[nodiscard]] explicit operator bool() const noexcept { + return is_valid(); + } void swap(type_id& other) noexcept { - std::swap(id_, other.id_); + std::swap(data_, other.data_); } [[nodiscard]] std::size_t get_hash() const noexcept { - return detail::hash_combiner{}(id_); + return data_ != nullptr ? detail::hash_combiner{}(data_) : 0; } [[nodiscard]] std::strong_ordering operator<=>(const type_id& other) const = default; private: - std::uintptr_t id_{}; + template < detail::type_family T > + friend class type_base; + + explicit type_id(const detail::type_data_base* data) + : data_{data} {} + + private: + const detail::type_data_base* data_{}; + }; +} + +namespace std +{ + template <> + struct hash { + size_t operator()(const meta_hpp::type_id& id) const noexcept { + return id.get_hash(); + } }; } @@ -2505,8 +2527,7 @@ namespace meta_hpp } [[nodiscard]] id_type get_id() const noexcept { - // NOLINTNEXTLINE(*-reinterpret-cast) - return id_type{reinterpret_cast(data_)}; + return id_type{data_}; } [[nodiscard]] type_kind get_kind() const noexcept { @@ -5597,8 +5618,14 @@ namespace meta_hpp template < typename... Args > uvalue invoke(const function& function, Args&&... args); + template < typename... Args > + uresult try_invoke(const function& function, Args&&... args); + template < detail::function_pointer_kind Function, typename... Args > uvalue invoke(Function function_ptr, Args&&... args); + + template < detail::function_pointer_kind Function, typename... Args > + uresult try_invoke(Function function_ptr, Args&&... args); } namespace meta_hpp @@ -5606,8 +5633,14 @@ namespace meta_hpp template < typename Instance > uvalue invoke(const member& member, Instance&& instance); + template < typename Instance > + uresult try_invoke(const member& member, Instance&& instance); + template < detail::member_pointer_kind Member, typename Instance > uvalue invoke(Member member_ptr, Instance&& instance); + + template < detail::member_pointer_kind Member, typename Instance > + uresult try_invoke(Member member_ptr, Instance&& instance); } namespace meta_hpp @@ -5615,53 +5648,59 @@ namespace meta_hpp template < typename Instance, typename... Args > uvalue invoke(const method& method, Instance&& instance, Args&&... args); + template < typename Instance, typename... Args > + uresult try_invoke(const method& method, Instance&& instance, Args&&... args); + template < detail::method_pointer_kind Method, typename Instance, typename... Args > uvalue invoke(Method method_ptr, Instance&& instance, Args&&... args); + + template < detail::method_pointer_kind Method, typename Instance, typename... Args > + uresult try_invoke(Method method_ptr, Instance&& instance, Args&&... args); } namespace meta_hpp { template < typename... Args > - bool is_invocable_with(const function& function); + bool is_invocable_with(const function& function) noexcept; template < typename... Args > - bool is_invocable_with(const function& function, Args&&... args); + bool is_invocable_with(const function& function, Args&&... args) noexcept; template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function); + bool is_invocable_with(Function) noexcept; template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function, Args&&... args); + bool is_invocable_with(Function, Args&&... args) noexcept; } namespace meta_hpp { template < typename Instance > - bool is_invocable_with(const member& member); + bool is_invocable_with(const member& member) noexcept; template < typename Instance > - bool is_invocable_with(const member& member, Instance&& instance); + bool is_invocable_with(const member& member, Instance&& instance) noexcept; template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member); + bool is_invocable_with(Member) noexcept; template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member, Instance&& instance); + bool is_invocable_with(Member, Instance&& instance) noexcept; } namespace meta_hpp { template < typename Instance, typename... Args > - bool is_invocable_with(const method& method); + bool is_invocable_with(const method& method) noexcept; template < typename Instance, typename... Args > - bool is_invocable_with(const method& method, Instance&& instance, Args&&... args); + bool is_invocable_with(const method& method, Instance&& instance, Args&&... args) noexcept; template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method); + bool is_invocable_with(Method) noexcept; template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method, Instance&& instance, Args&&... args); + bool is_invocable_with(Method, Instance&& instance, Args&&... args) noexcept; } namespace meta_hpp::detail @@ -6178,7 +6217,7 @@ namespace meta_hpp::detail namespace meta_hpp::detail { template < typename ArgTypeList > - bool can_cast_all_uargs(type_registry& registry, std::span args) { + bool can_cast_all_uargs(type_registry& registry, std::span args) noexcept { if ( args.size() != type_list_arity_v ) { return false; } @@ -6189,7 +6228,7 @@ namespace meta_hpp::detail } template < typename ArgTypeList > - bool can_cast_all_uargs(type_registry& registry, std::span args) { + bool can_cast_all_uargs(type_registry& registry, std::span args) noexcept { if ( args.size() != type_list_arity_v ) { return false; } @@ -6293,7 +6332,7 @@ namespace meta_hpp::detail } template < function_pointer_kind Function > - uerror raw_function_invoke_error(type_registry& registry, std::span args) { + uerror raw_function_invoke_error(type_registry& registry, std::span args) noexcept { using ft = function_traits; using argument_types = typename ft::argument_types; @@ -6734,7 +6773,7 @@ namespace meta_hpp::detail } template < member_pointer_kind Member > - uerror raw_member_getter_error(type_registry& registry, const uinst_base& inst) { + uerror raw_member_getter_error(type_registry& registry, const uinst_base& inst) noexcept { using mt = member_traits; using class_type = typename mt::class_type; @@ -6787,7 +6826,7 @@ namespace meta_hpp::detail } template < member_pointer_kind Member > - uerror raw_member_setter_error(type_registry& registry, const uinst_base& inst, const uarg_base& arg) { + uerror raw_member_setter_error(type_registry& registry, const uinst_base& inst, const uarg_base& arg) noexcept { using mt = member_traits; using class_type = typename mt::class_type; using value_type = typename mt::value_type; @@ -7066,7 +7105,7 @@ namespace meta_hpp::detail } template < method_pointer_kind Method > - uerror raw_method_invoke_error(type_registry& registry, const uinst_base& inst, std::span args) { + uerror raw_method_invoke_error(type_registry& registry, const uinst_base& inst, std::span args) noexcept { using mt = method_traits; using qualified_type = typename mt::qualified_type; using argument_types = typename mt::argument_types; @@ -7322,17 +7361,17 @@ namespace meta_hpp namespace meta_hpp { template < typename... Args > - bool is_invocable_with(const function& function) { + bool is_invocable_with(const function& function) noexcept { return function.is_invocable_with(); } template < typename... Args > - bool is_invocable_with(const function& function, Args&&... args) { + bool is_invocable_with(const function& function, Args&&... args) noexcept { return function.is_invocable_with(std::forward(args)...); } template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function) { + bool is_invocable_with(Function) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const std::array vargs{uarg_base{registry, type_list{}}...}; @@ -7340,7 +7379,7 @@ namespace meta_hpp } template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function, Args&&... args) { + bool is_invocable_with(Function, Args&&... args) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const std::array vargs{uarg_base{registry, std::forward(args)}...}; @@ -7351,17 +7390,17 @@ namespace meta_hpp namespace meta_hpp { template < typename Instance > - bool is_invocable_with(const member& member) { + bool is_invocable_with(const member& member) noexcept { return member.is_gettable_with(); } template < typename Instance > - bool is_invocable_with(const member& member, Instance&& instance) { + bool is_invocable_with(const member& member, Instance&& instance) noexcept { return member.is_gettable_with(std::forward(instance)); } template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member) { + bool is_invocable_with(Member) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, type_list{}}; @@ -7369,7 +7408,7 @@ namespace meta_hpp } template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member, Instance&& instance) { + bool is_invocable_with(Member, Instance&& instance) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, std::forward(instance)}; @@ -7380,17 +7419,17 @@ namespace meta_hpp namespace meta_hpp { template < typename Instance, typename... Args > - bool is_invocable_with(const method& method) { + bool is_invocable_with(const method& method) noexcept { return method.is_invocable_with(); } template < typename Instance, typename... Args > - bool is_invocable_with(const method& method, Instance&& instance, Args&&... args) { + bool is_invocable_with(const method& method, Instance&& instance, Args&&... args) noexcept { return method.is_invocable_with(std::forward(instance), std::forward(args)...); } template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method) { + bool is_invocable_with(Method) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, type_list{}}; @@ -7399,7 +7438,7 @@ namespace meta_hpp } template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method, Instance&& instance, Args&&... args) { + bool is_invocable_with(Method, Instance&& instance, Args&&... args) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, std::forward(instance)}; @@ -7537,7 +7576,7 @@ namespace meta_hpp::detail } template < class_kind Class, typename... Args > - uerror raw_constructor_create_error(type_registry& registry, std::span args) { + uerror raw_constructor_create_error(type_registry& registry, std::span args) noexcept { using ct = constructor_traits; using argument_types = typename ct::argument_types; @@ -7733,7 +7772,7 @@ namespace meta_hpp::detail } template < class_kind Class > - uerror raw_destructor_destroy_error(type_registry& registry, const uarg_base& arg) { + uerror raw_destructor_destroy_error(type_registry& registry, const uarg_base& arg) noexcept { using dt = destructor_traits; using class_type = typename dt::class_type; @@ -8007,7 +8046,7 @@ namespace meta_hpp::detail } template < pointer_kind Pointer > - uerror raw_variable_setter_error(type_registry& registry, const uarg_base& arg) { + uerror raw_variable_setter_error(type_registry& registry, const uarg_base& arg) noexcept { using pt = pointer_traits; using data_type = typename pt::data_type; diff --git a/develop/untests/meta_types/type_id_tests.cpp b/develop/untests/meta_types/type_id_tests.cpp new file mode 100644 index 0000000..8ba788f --- /dev/null +++ b/develop/untests/meta_types/type_id_tests.cpp @@ -0,0 +1,42 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include +#include + +TEST_CASE("meta/meta_types/type_id") { + namespace meta = meta_hpp; + + SUBCASE("ctors/0") { + const meta::type_id id; + CHECK_FALSE(id); + CHECK_FALSE(id.is_valid()); + } + + SUBCASE("ctors/1") { + const meta::type_id int_id = meta::resolve_type().get_id(); + const meta::type_id float_id = meta::resolve_type().get_id(); + + REQUIRE(int_id); + REQUIRE(float_id); + + CHECK_FALSE(int_id == float_id); + CHECK(int_id != float_id); + CHECK((int_id < float_id || (float_id < int_id))); + } + + SUBCASE("get_hash") { + const meta::type_id int_id = meta::resolve_type().get_id(); + const meta::type_id float_id = meta::resolve_type().get_id(); + + REQUIRE(int_id); + REQUIRE(float_id); + + CHECK(meta::type_id{}.get_hash() == 0); + CHECK_FALSE(int_id.get_hash() == float_id.get_hash()); + CHECK(int_id.get_hash() == meta::resolve_type().get_id().get_hash()); + } +} diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index 8409d96..940a073 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -222,10 +222,10 @@ namespace meta_hpp using metadata_map = std::map>; using typedef_map = std::map>; + using any_type_list = std::vector; using class_list = std::vector; using enum_list = std::vector; - using any_type_list = std::vector; using argument_list = std::vector; using constructor_list = std::vector; using destructor_list = std::vector; diff --git a/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp b/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp index a943201..7a15ec4 100644 --- a/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp +++ b/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp @@ -341,7 +341,7 @@ namespace meta_hpp::detail namespace meta_hpp::detail { template < typename ArgTypeList > - bool can_cast_all_uargs(type_registry& registry, std::span args) { + bool can_cast_all_uargs(type_registry& registry, std::span args) noexcept { if ( args.size() != type_list_arity_v ) { return false; } @@ -352,7 +352,7 @@ namespace meta_hpp::detail } template < typename ArgTypeList > - bool can_cast_all_uargs(type_registry& registry, std::span args) { + bool can_cast_all_uargs(type_registry& registry, std::span args) noexcept { if ( args.size() != type_list_arity_v ) { return false; } diff --git a/headers/meta.hpp/meta_invoke.hpp b/headers/meta.hpp/meta_invoke.hpp index 01eb38b..0a2e228 100644 --- a/headers/meta.hpp/meta_invoke.hpp +++ b/headers/meta.hpp/meta_invoke.hpp @@ -15,8 +15,14 @@ namespace meta_hpp template < typename... Args > uvalue invoke(const function& function, Args&&... args); + template < typename... Args > + uresult try_invoke(const function& function, Args&&... args); + template < detail::function_pointer_kind Function, typename... Args > uvalue invoke(Function function_ptr, Args&&... args); + + template < detail::function_pointer_kind Function, typename... Args > + uresult try_invoke(Function function_ptr, Args&&... args); } namespace meta_hpp @@ -24,8 +30,14 @@ namespace meta_hpp template < typename Instance > uvalue invoke(const member& member, Instance&& instance); + template < typename Instance > + uresult try_invoke(const member& member, Instance&& instance); + template < detail::member_pointer_kind Member, typename Instance > uvalue invoke(Member member_ptr, Instance&& instance); + + template < detail::member_pointer_kind Member, typename Instance > + uresult try_invoke(Member member_ptr, Instance&& instance); } namespace meta_hpp @@ -33,51 +45,57 @@ namespace meta_hpp template < typename Instance, typename... Args > uvalue invoke(const method& method, Instance&& instance, Args&&... args); + template < typename Instance, typename... Args > + uresult try_invoke(const method& method, Instance&& instance, Args&&... args); + template < detail::method_pointer_kind Method, typename Instance, typename... Args > uvalue invoke(Method method_ptr, Instance&& instance, Args&&... args); + + template < detail::method_pointer_kind Method, typename Instance, typename... Args > + uresult try_invoke(Method method_ptr, Instance&& instance, Args&&... args); } namespace meta_hpp { template < typename... Args > - bool is_invocable_with(const function& function); + bool is_invocable_with(const function& function) noexcept; template < typename... Args > - bool is_invocable_with(const function& function, Args&&... args); + bool is_invocable_with(const function& function, Args&&... args) noexcept; template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function); + bool is_invocable_with(Function) noexcept; template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function, Args&&... args); + bool is_invocable_with(Function, Args&&... args) noexcept; } namespace meta_hpp { template < typename Instance > - bool is_invocable_with(const member& member); + bool is_invocable_with(const member& member) noexcept; template < typename Instance > - bool is_invocable_with(const member& member, Instance&& instance); + bool is_invocable_with(const member& member, Instance&& instance) noexcept; template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member); + bool is_invocable_with(Member) noexcept; template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member, Instance&& instance); + bool is_invocable_with(Member, Instance&& instance) noexcept; } namespace meta_hpp { template < typename Instance, typename... Args > - bool is_invocable_with(const method& method); + bool is_invocable_with(const method& method) noexcept; template < typename Instance, typename... Args > - bool is_invocable_with(const method& method, Instance&& instance, Args&&... args); + bool is_invocable_with(const method& method, Instance&& instance, Args&&... args) noexcept; template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method); + bool is_invocable_with(Method) noexcept; template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method, Instance&& instance, Args&&... args); + bool is_invocable_with(Method, Instance&& instance, Args&&... args) noexcept; } diff --git a/headers/meta.hpp/meta_invoke/invoke.hpp b/headers/meta.hpp/meta_invoke/invoke.hpp index 2a079b4..e08d420 100644 --- a/headers/meta.hpp/meta_invoke/invoke.hpp +++ b/headers/meta.hpp/meta_invoke/invoke.hpp @@ -134,17 +134,17 @@ namespace meta_hpp namespace meta_hpp { template < typename... Args > - bool is_invocable_with(const function& function) { + bool is_invocable_with(const function& function) noexcept { return function.is_invocable_with(); } template < typename... Args > - bool is_invocable_with(const function& function, Args&&... args) { + bool is_invocable_with(const function& function, Args&&... args) noexcept { return function.is_invocable_with(std::forward(args)...); } template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function) { + bool is_invocable_with(Function) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const std::array vargs{uarg_base{registry, type_list{}}...}; @@ -152,7 +152,7 @@ namespace meta_hpp } template < typename... Args, detail::function_pointer_kind Function > - bool is_invocable_with(Function, Args&&... args) { + bool is_invocable_with(Function, Args&&... args) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const std::array vargs{uarg_base{registry, std::forward(args)}...}; @@ -163,17 +163,17 @@ namespace meta_hpp namespace meta_hpp { template < typename Instance > - bool is_invocable_with(const member& member) { + bool is_invocable_with(const member& member) noexcept { return member.is_gettable_with(); } template < typename Instance > - bool is_invocable_with(const member& member, Instance&& instance) { + bool is_invocable_with(const member& member, Instance&& instance) noexcept { return member.is_gettable_with(std::forward(instance)); } template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member) { + bool is_invocable_with(Member) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, type_list{}}; @@ -181,7 +181,7 @@ namespace meta_hpp } template < typename Instance, detail::member_pointer_kind Member > - bool is_invocable_with(Member, Instance&& instance) { + bool is_invocable_with(Member, Instance&& instance) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, std::forward(instance)}; @@ -192,17 +192,17 @@ namespace meta_hpp namespace meta_hpp { template < typename Instance, typename... Args > - bool is_invocable_with(const method& method) { + bool is_invocable_with(const method& method) noexcept { return method.is_invocable_with(); } template < typename Instance, typename... Args > - bool is_invocable_with(const method& method, Instance&& instance, Args&&... args) { + bool is_invocable_with(const method& method, Instance&& instance, Args&&... args) noexcept { return method.is_invocable_with(std::forward(instance), std::forward(args)...); } template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method) { + bool is_invocable_with(Method) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, type_list{}}; @@ -211,7 +211,7 @@ namespace meta_hpp } template < typename Instance, typename... Args, detail::method_pointer_kind Method > - bool is_invocable_with(Method, Instance&& instance, Args&&... args) { + bool is_invocable_with(Method, Instance&& instance, Args&&... args) noexcept { using namespace detail; type_registry& registry{type_registry::instance()}; const uinst_base vinst{registry, std::forward(instance)}; diff --git a/headers/meta.hpp/meta_states/constructor.hpp b/headers/meta.hpp/meta_states/constructor.hpp index 99bead5..28c8aff 100644 --- a/headers/meta.hpp/meta_states/constructor.hpp +++ b/headers/meta.hpp/meta_states/constructor.hpp @@ -80,7 +80,7 @@ namespace meta_hpp::detail } template < class_kind Class, typename... Args > - uerror raw_constructor_create_error(type_registry& registry, std::span args) { + uerror raw_constructor_create_error(type_registry& registry, std::span args) noexcept { using ct = constructor_traits; using argument_types = typename ct::argument_types; diff --git a/headers/meta.hpp/meta_states/destructor.hpp b/headers/meta.hpp/meta_states/destructor.hpp index 54ea8ce..57dd59c 100644 --- a/headers/meta.hpp/meta_states/destructor.hpp +++ b/headers/meta.hpp/meta_states/destructor.hpp @@ -37,7 +37,7 @@ namespace meta_hpp::detail } template < class_kind Class > - uerror raw_destructor_destroy_error(type_registry& registry, const uarg_base& arg) { + uerror raw_destructor_destroy_error(type_registry& registry, const uarg_base& arg) noexcept { using dt = destructor_traits; using class_type = typename dt::class_type; diff --git a/headers/meta.hpp/meta_states/function.hpp b/headers/meta.hpp/meta_states/function.hpp index 92dc4dd..05ef491 100644 --- a/headers/meta.hpp/meta_states/function.hpp +++ b/headers/meta.hpp/meta_states/function.hpp @@ -64,7 +64,7 @@ namespace meta_hpp::detail } template < function_pointer_kind Function > - uerror raw_function_invoke_error(type_registry& registry, std::span args) { + uerror raw_function_invoke_error(type_registry& registry, std::span args) noexcept { using ft = function_traits; using argument_types = typename ft::argument_types; diff --git a/headers/meta.hpp/meta_states/member.hpp b/headers/meta.hpp/meta_states/member.hpp index 151f71e..b7c63f5 100644 --- a/headers/meta.hpp/meta_states/member.hpp +++ b/headers/meta.hpp/meta_states/member.hpp @@ -76,7 +76,7 @@ namespace meta_hpp::detail } template < member_pointer_kind Member > - uerror raw_member_getter_error(type_registry& registry, const uinst_base& inst) { + uerror raw_member_getter_error(type_registry& registry, const uinst_base& inst) noexcept { using mt = member_traits; using class_type = typename mt::class_type; @@ -129,7 +129,7 @@ namespace meta_hpp::detail } template < member_pointer_kind Member > - uerror raw_member_setter_error(type_registry& registry, const uinst_base& inst, const uarg_base& arg) { + uerror raw_member_setter_error(type_registry& registry, const uinst_base& inst, const uarg_base& arg) noexcept { using mt = member_traits; using class_type = typename mt::class_type; using value_type = typename mt::value_type; diff --git a/headers/meta.hpp/meta_states/method.hpp b/headers/meta.hpp/meta_states/method.hpp index 685e20b..f212119 100644 --- a/headers/meta.hpp/meta_states/method.hpp +++ b/headers/meta.hpp/meta_states/method.hpp @@ -71,7 +71,7 @@ namespace meta_hpp::detail } template < method_pointer_kind Method > - uerror raw_method_invoke_error(type_registry& registry, const uinst_base& inst, std::span args) { + uerror raw_method_invoke_error(type_registry& registry, const uinst_base& inst, std::span args) noexcept { using mt = method_traits; using qualified_type = typename mt::qualified_type; using argument_types = typename mt::argument_types; diff --git a/headers/meta.hpp/meta_states/variable.hpp b/headers/meta.hpp/meta_states/variable.hpp index 535bc0a..7ced140 100644 --- a/headers/meta.hpp/meta_states/variable.hpp +++ b/headers/meta.hpp/meta_states/variable.hpp @@ -68,7 +68,7 @@ namespace meta_hpp::detail } template < pointer_kind Pointer > - uerror raw_variable_setter_error(type_registry& registry, const uarg_base& arg) { + uerror raw_variable_setter_error(type_registry& registry, const uarg_base& arg) noexcept { using pt = pointer_traits; using data_type = typename pt::data_type; diff --git a/headers/meta.hpp/meta_types.hpp b/headers/meta.hpp/meta_types.hpp index 270df21..bf40c54 100644 --- a/headers/meta.hpp/meta_types.hpp +++ b/headers/meta.hpp/meta_types.hpp @@ -52,21 +52,43 @@ namespace meta_hpp public: type_id() = default; - explicit type_id(std::uintptr_t id) - : id_{id} {} + [[nodiscard]] bool is_valid() const noexcept { + return data_ != nullptr; + } + + [[nodiscard]] explicit operator bool() const noexcept { + return is_valid(); + } void swap(type_id& other) noexcept { - std::swap(id_, other.id_); + std::swap(data_, other.data_); } [[nodiscard]] std::size_t get_hash() const noexcept { - return detail::hash_combiner{}(id_); + return data_ != nullptr ? detail::hash_combiner{}(data_) : 0; } [[nodiscard]] std::strong_ordering operator<=>(const type_id& other) const = default; private: - std::uintptr_t id_{}; + template < detail::type_family T > + friend class type_base; + + explicit type_id(const detail::type_data_base* data) + : data_{data} {} + + private: + const detail::type_data_base* data_{}; + }; +} + +namespace std +{ + template <> + struct hash { + size_t operator()(const meta_hpp::type_id& id) const noexcept { + return id.get_hash(); + } }; } @@ -100,8 +122,7 @@ namespace meta_hpp } [[nodiscard]] id_type get_id() const noexcept { - // NOLINTNEXTLINE(*-reinterpret-cast) - return id_type{reinterpret_cast(data_)}; + return id_type{data_}; } [[nodiscard]] type_kind get_kind() const noexcept {