fix uvalue copy traits

ref: https://github.com/BlackMATov/meta.hpp/issues/100
This commit is contained in:
BlackMATov
2024-09-05 06:30:44 +07:00
parent 8f74952047
commit 5d5ba52045
3 changed files with 105 additions and 1 deletions

View File

@@ -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;

View File

@@ -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<int, 1>{}}.has_copy_op());
CHECK_FALSE(meta::uvalue{std::array<std::unique_ptr<int>, 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<std::unique_ptr<int>>{}}.has_copy_op());
CHECK(meta::uvalue{std::shared_ptr<int>{}}.has_copy_op());
{
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
std::unique_ptr u = std::make_unique<int>(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<ref_t>());
CHECK(v.as<ref_t>().get().get() == u.get());
}
CHECK(meta::uvalue{std::make_tuple(42, std::make_shared<int>(42))}.has_copy_op());
CHECK_FALSE(meta::uvalue{std::make_tuple(42, std::make_unique<int>(42))}.has_copy_op());
}
}
SUBCASE("unmap") {

View File

@@ -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<T> && std::is_copy_constructible_v<T>)
struct copy_traits<T> {
uvalue operator()(const T& v) const {
return uvalue{v};
}
};
template < typename T, std::size_t Size >
requires has_copy_traits<T>
struct copy_traits<std::array<T, Size>> {
using value_t = std::array<T, Size>;
uvalue operator()(const value_t& v) const {
return uvalue{v};
}
};
template < typename T, typename Traits, typename Allocator >
requires has_copy_traits<T>
struct copy_traits<std::basic_string<T, Traits, Allocator>> {
using value_t = std::basic_string<T, Traits, Allocator>;
uvalue operator()(const value_t& v) const {
return uvalue{v};
}
};
template < typename T, typename Traits >
requires has_copy_traits<T>
struct copy_traits<std::basic_string_view<T, Traits>> {
using value_t = std::basic_string_view<T, Traits>;
uvalue operator()(const value_t& v) const {
return uvalue{v};
}
};
template < typename T, typename Allocator >
requires has_copy_traits<T>
struct copy_traits<std::vector<T, Allocator>> {
using value_t = std::vector<T, Allocator>;
uvalue operator()(const value_t& v) const {
return uvalue{v};
}
};
template < typename T >
struct copy_traits<std::shared_ptr<T>> {
using value_t = std::shared_ptr<T>;
uvalue operator()(const value_t& v) const {
return uvalue{v};
}
};
template < typename T >
struct copy_traits<std::reference_wrapper<T>> {
using value_t = std::reference_wrapper<T>;
uvalue operator()(const value_t& v) const {
return uvalue{v};
}
};
template < typename... Ts >
requires(... && has_copy_traits<Ts>)
struct copy_traits<std::tuple<Ts...>> {
using value_t = std::tuple<Ts...>;
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<T> { \
uvalue operator()(const T& v) const { \
return uvalue{v}; \
} \
}; \
}