diff --git a/headers/meta.hpp/meta_binds.hpp b/headers/meta.hpp/meta_binds.hpp index 84bae19..54c1bdf 100644 --- a/headers/meta.hpp/meta_binds.hpp +++ b/headers/meta.hpp/meta_binds.hpp @@ -419,7 +419,13 @@ namespace meta_hpp template < detail::class_kind Class > class_bind class_(metadata_map metadata = {}) { - return class_bind{std::move(metadata)}; + class_bind bind{std::move(metadata)}; + + if constexpr ( std::is_destructible_v ) { + bind.destructor_(); + } + + return bind; } template < detail::enum_kind Enum > diff --git a/headers/meta.hpp/meta_detail/type_traits/destructor_traits.hpp b/headers/meta.hpp/meta_detail/type_traits/destructor_traits.hpp index 485767e..5b442ea 100644 --- a/headers/meta.hpp/meta_detail/type_traits/destructor_traits.hpp +++ b/headers/meta.hpp/meta_detail/type_traits/destructor_traits.hpp @@ -12,6 +12,7 @@ namespace meta_hpp::detail { enum class destructor_flags : std::uint32_t { is_noexcept = 1 << 0, + is_virtual = 1 << 1, }; META_HPP_BITFLAGS_OPERATORS_DECL(destructor_flags) @@ -31,6 +32,10 @@ namespace meta_hpp::detail flags.set(destructor_flags::is_noexcept); } + if constexpr ( std::has_virtual_destructor_v ) { + flags.set(destructor_flags::is_virtual); + } + return flags; } }; diff --git a/singles/headers/meta.hpp/meta_all.hpp b/singles/headers/meta.hpp/meta_all.hpp index 3563243..b669d8b 100644 --- a/singles/headers/meta.hpp/meta_all.hpp +++ b/singles/headers/meta.hpp/meta_all.hpp @@ -1072,6 +1072,7 @@ namespace meta_hpp::detail { enum class destructor_flags : std::uint32_t { is_noexcept = 1 << 0, + is_virtual = 1 << 1, }; META_HPP_BITFLAGS_OPERATORS_DECL(destructor_flags) @@ -1091,6 +1092,10 @@ namespace meta_hpp::detail flags.set(destructor_flags::is_noexcept); } + if constexpr ( std::has_virtual_destructor_v ) { + flags.set(destructor_flags::is_virtual); + } + return flags; } }; @@ -3548,7 +3553,13 @@ namespace meta_hpp template < detail::class_kind Class > class_bind class_(metadata_map metadata = {}) { - return class_bind{std::move(metadata)}; + class_bind bind{std::move(metadata)}; + + if constexpr ( std::is_destructible_v ) { + bind.destructor_(); + } + + return bind; } template < detail::enum_kind Enum > diff --git a/untests/meta_states/dtor_tests.cpp b/untests/meta_states/dtor_tests.cpp new file mode 100644 index 0000000..e91730f --- /dev/null +++ b/untests/meta_states/dtor_tests.cpp @@ -0,0 +1,99 @@ +/******************************************************************************* + * 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-2022, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include "../meta_untests.hpp" + +namespace +{ + class clazz_closed_dtor { + public: + ~clazz_closed_dtor() = delete; + }; + + class clazz_opened_dtor { + public: + ~clazz_opened_dtor() = default; + }; + + class clazz_virtual_dtor { + public: + virtual ~clazz_virtual_dtor() noexcept(false) = default; + }; + + class clazz_dtor_metadata { + public: + virtual ~clazz_dtor_metadata() = default; + }; +} + +TEST_CASE("meta/meta_states/dtor") { + namespace meta = meta_hpp; + using namespace std::string_literals; + + meta::class_(); + meta::class_(); + meta::class_(); + + meta::class_() + .destructor_({ + .metadata{ + {"desc", meta::uvalue{"virtual dtor"s}} + } + }); + + SUBCASE("closed_dtor") { + const meta::class_type clazz_type = meta::resolve_type(); + REQUIRE(clazz_type); + + CHECK(clazz_type.get_destructors().empty()); + } + + SUBCASE("opened_dtor") { + const meta::class_type clazz_type = meta::resolve_type(); + REQUIRE(clazz_type); + + REQUIRE(clazz_type.get_destructors().size() == 1); + auto&& [_, dtor] = *clazz_type.get_destructors().begin(); + + CHECK(dtor.get_type().get_class_type() == meta::resolve_type()); + CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_noexcept); + } + + SUBCASE("virtual_dtor") { + const meta::class_type clazz_type = meta::resolve_type(); + REQUIRE(clazz_type); + + REQUIRE(clazz_type.get_destructors().size() == 1); + auto&& [_, dtor] = *clazz_type.get_destructors().begin(); + + CHECK(dtor.get_type().get_class_type() == meta::resolve_type()); + CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_virtual); + } + + SUBCASE("virtual_dtor") { + const meta::class_type clazz_type = meta::resolve_type(); + REQUIRE(clazz_type); + + REQUIRE(clazz_type.get_destructors().size() == 1); + auto&& [_, dtor] = *clazz_type.get_destructors().begin(); + + CHECK(dtor.get_type().get_class_type() == meta::resolve_type()); + CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_virtual); + } + + SUBCASE("dtor_metadata") { + const meta::class_type clazz_type = meta::resolve_type(); + REQUIRE(clazz_type); + + REQUIRE(clazz_type.get_destructors().size() == 1); + auto&& [_, dtor] = *clazz_type.get_destructors().begin(); + + CHECK(dtor.get_type().get_class_type() == meta::resolve_type()); + CHECK(dtor.get_type().get_flags() == (meta::destructor_flags::is_noexcept | meta::destructor_flags::is_virtual)); + + CHECK(dtor.get_metadata().at("desc") == "virtual dtor"s); + } +}