diff --git a/include/proxy/v4/detail/facade_meta_traits.h b/include/proxy/v4/detail/facade_meta_traits.h index 8a6298e..86e7d6d 100644 --- a/include/proxy/v4/detail/facade_meta_traits.h +++ b/include/proxy/v4/detail/facade_meta_traits.h @@ -140,44 +140,18 @@ struct invoker; PRO4D_DEF_OVERLOAD_SPECIALIZATIONS(PRO4D_DEF_INVOKER) #undef PRO4D_DEF_INVOKER -template -struct PRO4D_ENFORCE_EBO inplace_meta_storage : M { - using M::M; - - inplace_meta_storage() = default; - inplace_meta_storage(const inplace_meta_storage&) = default; - template - requires(std::is_nothrow_convertible_v) - inplace_meta_storage(const inplace_meta_storage& rhs) noexcept - : M(static_cast(*rhs)) {} - inplace_meta_storage& operator=(const inplace_meta_storage&) = default; - template - requires(std::is_nothrow_convertible_v) - inplace_meta_storage& - operator=(const inplace_meta_storage& rhs) noexcept { - static_cast(*this) = static_cast(*rhs); - return *this; - } - - const M& operator*() const noexcept { return *this; } -}; - template struct static_meta_storage { static_meta_storage() = default; - template - requires(std::is_nothrow_convertible_v) - static_meta_storage(const static_meta_storage& rhs) noexcept - : ptr_(std::addressof(static_cast(*rhs))) {} + template + explicit static_meta_storage(std::in_place_type_t

) + : ptr_(std::addressof(storage

)) {} template requires(std::is_nothrow_convertible_v) static_meta_storage& operator=(const static_meta_storage& rhs) noexcept { ptr_ = std::addressof(static_cast(*rhs)); return *this; } - template - explicit static_meta_storage(std::in_place_type_t

) - : ptr_(std::addressof(storage

)) {} bool has_value() const noexcept { return ptr_ != nullptr; } void reset() noexcept { ptr_ = nullptr; } const M& operator*() const noexcept { return *ptr_; } @@ -189,6 +163,27 @@ struct static_meta_storage { static inline const M storage{std::in_place_type

}; }; +template +struct inplace_meta_storage : M { + using M::M; + + template + requires(std::is_nothrow_convertible_v) + inplace_meta_storage& + operator=(const inplace_meta_storage& rhs) noexcept { + static_cast(*this) = *rhs; + return *this; + } + template + requires(std::is_nothrow_convertible_v) + inplace_meta_storage& operator=(const static_meta_storage& rhs) noexcept { + static_cast(*this) = *rhs; + return *this; + } + + const M& operator*() const noexcept { return *this; } +}; + } // namespace detail struct compact_facade_meta_traits { diff --git a/tests/proxy_lifetime_tests.cpp b/tests/proxy_lifetime_tests.cpp index 701e2ce..ed17f4c 100644 --- a/tests/proxy_lifetime_tests.cpp +++ b/tests/proxy_lifetime_tests.cpp @@ -1217,6 +1217,32 @@ TEST(ProxyLifetimeTests, Test_CopySubstitution_FromNull) { ASSERT_FALSE(p2.has_value()); } +TEST(ProxyLifetimeTests, Test_CopySubstitution_MixedMetaStorage) { + struct Super : pro::facade_builder // + ::add_convention // + ::support_copy // + ::support_relocation // + ::support_destruction // + ::build {}; + struct Derived : pro::facade_builder // + ::add_facade_with_substitution // + ::build {}; + static_assert( + pro::detail::specialization_of>, + pro::detail::inplace_meta_storage>); + static_assert( + pro::detail::specialization_of>, + pro::detail::static_meta_storage>); + int v = 123; + pro::proxy p1 = &v; + pro::proxy p2 = p1; + ASSERT_EQ(ToString(*p1), "123"); + ASSERT_EQ(ToString(*p2), "123"); +} + TEST(ProxyLifetimeTests, Test_MoveSubstitution_FromValue) { utils::LifetimeTracker tracker; std::vector expected_ops;