From 6d14b77e50bd59d6bfdc99d403c8061e1e2dfe1d Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Mon, 3 Mar 2025 19:47:52 +0800 Subject: [PATCH] Implement make_proxy_view and optimize `proxiable_target` --- proxy.h | 59 +++++++++++++++++++--------------- tests/proxy_creation_tests.cpp | 21 ++++++++++++ 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/proxy.h b/proxy.h index 2d599954..311d2d9f 100644 --- a/proxy.h +++ b/proxy.h @@ -1175,6 +1175,23 @@ const proxy&& access_proxy(const A&& a) noexcept { namespace details { +template +struct observer_ptr { + public: + explicit observer_ptr(LR lr) : lr_(lr) {} + observer_ptr(const observer_ptr&) = default; + auto operator->() noexcept { return std::addressof(lr_); } + auto operator->() const noexcept + { return std::addressof(static_cast(lr_)); } + LR operator*() & noexcept { return static_cast(lr_); } + CLR operator*() const& noexcept { return static_cast(lr_); } + RR operator*() && noexcept { return static_cast(lr_); } + CRR operator*() const&& noexcept { return static_cast(lr_); } + + private: + LR lr_; +}; + #if __STDC_HOSTED__ template T* allocate(const Alloc& alloc, Args&&... args) { @@ -1443,6 +1460,9 @@ constexpr proxy make_proxy_shared_impl(Args&&... args) { } // namespace details +template struct observer_facade; +template using proxy_view = proxy>; + template concept inplace_proxiable_target = proxiable, F>; @@ -1470,10 +1490,19 @@ constexpr proxy make_proxy_inplace(T&& value) std::in_place, std::forward(value)}; } -#if __STDC_HOSTED__ template -concept proxiable_target = inplace_proxiable_target || - proxiable>, F>; +concept proxiable_target = proxiable< + details::observer_ptr, observer_facade>; + +template +constexpr proxy_view make_proxy_view(T& value) noexcept { + return proxy_view{ + details::observer_ptr{value}}; +} + +#if __STDC_HOSTED__ +template struct weak_facade; +template using weak_proxy = proxy>; template constexpr proxy allocate_proxy(const Alloc& alloc, Args&&... args) @@ -1543,14 +1572,8 @@ constexpr proxy make_proxy_shared(T&& value) return details::make_proxy_shared_impl>( std::forward(value)); } - -template struct weak_facade; -template using weak_proxy = proxy>; #endif // __STDC_HOSTED__ -template struct observer_facade; -template using proxy_view = proxy>; - #ifdef __cpp_rtti class bad_proxy_cast : public std::bad_cast { public: @@ -1905,29 +1928,13 @@ using merge_facade_conv_t = typename add_upward_conversion_conv< F::constraints.copyability != constraint_level::trivial) ? F::constraints.relocatability : constraint_level::none>::type; -template -struct observer_ptr { - public: - explicit observer_ptr(std::remove_reference_t* ptr) : ptr_(ptr) {} - observer_ptr(const observer_ptr&) = default; - auto operator->() noexcept { return std::addressof(static_cast(*ptr_)); } - auto operator->() const noexcept - { return std::addressof(static_cast(*ptr_)); } - LR operator*() & noexcept { return static_cast(*ptr_); } - CLR operator*() const& noexcept { return static_cast(*ptr_); } - RR operator*() && noexcept { return static_cast(*ptr_); } - CRR operator*() const&& noexcept { return static_cast(*ptr_); } - - private: - std::remove_reference_t* ptr_; -}; struct proxy_view_dispatch : cast_dispatch_base { template auto operator()(T& value) const noexcept requires(requires { { std::addressof(*value) } noexcept; }) { return observer_ptr - {std::addressof(*value)}; + {*value}; } }; diff --git a/tests/proxy_creation_tests.cpp b/tests/proxy_creation_tests.cpp index 79605838..7fc21809 100644 --- a/tests/proxy_creation_tests.cpp +++ b/tests/proxy_creation_tests.cpp @@ -972,3 +972,24 @@ TEST(ProxyCreationTests, TestStdWeakPtrCompatibility) { } ASSERT_TRUE(tracker.GetOperations() == expected_ops); } + +TEST(ProxyCreationTests, TestMakeProxyView) { + struct TestFacade : pro::facade_builder + ::add_convention, int()&, int() const&, int() && noexcept, int() const&&> + ::build {}; + + struct { + int operator()()& noexcept { return 0; } + int operator()() const& noexcept { return 1; } + int operator()() && noexcept { return 2; } + int operator()() const&& noexcept { return 3; } + } test_callable; + + pro::proxy_view p = pro::make_proxy_view(test_callable); + static_assert(!noexcept((*p)())); + static_assert(noexcept((*std::move(p))())); + ASSERT_EQ((*p)(), 0); + ASSERT_EQ((*std::as_const(p))(), 1); + ASSERT_EQ((*std::move(p))(), 2); + ASSERT_EQ((*std::move(std::as_const(p)))(), 3); +}