diff --git a/develop/untests/meta_utilities/value2_tests.cpp b/develop/untests/meta_utilities/value2_tests.cpp index e5a5c76..3d60f55 100644 --- a/develop/untests/meta_utilities/value2_tests.cpp +++ b/develop/untests/meta_utilities/value2_tests.cpp @@ -90,6 +90,9 @@ namespace int ivec2_big::copy_constructor_counter{0}; } +META_HPP_DECLARE_COPY_TRAITS_FOR(ivec2) +META_HPP_DECLARE_COPY_TRAITS_FOR(ivec2_big) + TEST_CASE("meta/meta_utilities/value2") { namespace meta = meta_hpp; diff --git a/develop/untests/meta_utilities/value_tests.cpp b/develop/untests/meta_utilities/value_tests.cpp index 50ce7bc..49adcc4 100644 --- a/develop/untests/meta_utilities/value_tests.cpp +++ b/develop/untests/meta_utilities/value_tests.cpp @@ -109,6 +109,9 @@ namespace } } +META_HPP_DECLARE_COPY_TRAITS_FOR(ivec2) +META_HPP_DECLARE_COPY_TRAITS_FOR(ivec2_big) + TEST_CASE("meta/meta_utilities/value/_") { namespace meta = meta_hpp; @@ -497,6 +500,25 @@ TEST_CASE("meta/meta_utilities/value") { CHECK_FALSE(u.has_copy_op()); CHECK_THROWS(std::ignore = u.copy()); } + { + CHECK(meta::uvalue{std::array{}}.has_copy_op()); + CHECK_FALSE(meta::uvalue{std::array, 1>{}}.has_copy_op()); + CHECK(meta::uvalue{std::string{}}.has_copy_op()); + CHECK(meta::uvalue{std::string_view{}}.has_copy_op()); + CHECK(meta::uvalue{std::vector{42, 21}}.has_copy_op()); + CHECK_FALSE(meta::uvalue{std::vector>{}}.has_copy_op()); + CHECK(meta::uvalue{std::shared_ptr{}}.has_copy_op()); + { + using ref_t = std::reference_wrapper>; + std::unique_ptr u = std::make_unique(42); + CHECK(meta::uvalue{ref_t{u}}.has_copy_op()); + meta::uvalue v = meta::uvalue{ref_t{u}}.copy(); + CHECK(v.get_type() == meta::resolve_type()); + CHECK(v.as().get().get() == u.get()); + } + CHECK(meta::uvalue{std::make_tuple(42, std::make_shared(42))}.has_copy_op()); + CHECK_FALSE(meta::uvalue{std::make_tuple(42, std::make_unique(42))}.has_copy_op()); + } } SUBCASE("unmap") { diff --git a/headers/meta.hpp/meta_detail/value_traits/copy_traits.hpp b/headers/meta.hpp/meta_detail/value_traits/copy_traits.hpp index 37c1089..dcd63bd 100644 --- a/headers/meta.hpp/meta_detail/value_traits/copy_traits.hpp +++ b/headers/meta.hpp/meta_detail/value_traits/copy_traits.hpp @@ -22,10 +22,89 @@ namespace meta_hpp::detail namespace meta_hpp::detail { template < typename T > - requires requires(const T& v) { uvalue{v}; } + requires(!std::is_class_v && std::is_copy_constructible_v) struct copy_traits { uvalue operator()(const T& v) const { return uvalue{v}; } }; + + template < typename T, std::size_t Size > + requires has_copy_traits + struct copy_traits> { + using value_t = std::array; + + uvalue operator()(const value_t& v) const { + return uvalue{v}; + } + }; + + template < typename T, typename Traits, typename Allocator > + requires has_copy_traits + struct copy_traits> { + using value_t = std::basic_string; + + uvalue operator()(const value_t& v) const { + return uvalue{v}; + } + }; + + template < typename T, typename Traits > + requires has_copy_traits + struct copy_traits> { + using value_t = std::basic_string_view; + + uvalue operator()(const value_t& v) const { + return uvalue{v}; + } + }; + + template < typename T, typename Allocator > + requires has_copy_traits + struct copy_traits> { + using value_t = std::vector; + + uvalue operator()(const value_t& v) const { + return uvalue{v}; + } + }; + + template < typename T > + struct copy_traits> { + using value_t = std::shared_ptr; + + uvalue operator()(const value_t& v) const { + return uvalue{v}; + } + }; + + template < typename T > + struct copy_traits> { + using value_t = std::reference_wrapper; + + uvalue operator()(const value_t& v) const { + return uvalue{v}; + } + }; + + template < typename... Ts > + requires(... && has_copy_traits) + struct copy_traits> { + using value_t = std::tuple; + + uvalue operator()(const value_t& v) const { + return uvalue{v}; + } + }; } + +#define META_HPP_DECLARE_COPY_TRAITS_FOR(T) \ + namespace meta_hpp::detail \ + { \ + template <> \ + struct copy_traits { \ + uvalue operator()(const T& v) const { \ + return uvalue{v}; \ + } \ + }; \ + }