From c94e8b806bc1b5efadd6fd98604ba4cf924f7a2d Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Sat, 28 Sep 2024 17:35:43 +0800 Subject: [PATCH] Reduce semantics of proxy_invoke --- docs/PRO_DEF_FREE_DISPATCH.md | 2 +- docs/PRO_DEF_MEM_DISPATCH.md | 2 +- docs/access_proxy.md | 2 +- docs/conversion_dispatch/accessor.md | 2 +- docs/operator_dispatch/accessor.md | 10 ++-- docs/proxy_invoke.md | 14 ++--- proxy.h | 55 +++++++++---------- samples/access_proxy.cpp | 2 +- ..._msft_lib_proxy.cpp => msft_lib_proxy.cpp} | 2 +- samples/proxy_invoke.cpp | 2 +- 10 files changed, 44 insertions(+), 49 deletions(-) rename samples/{__msft_lib_proxy.cpp => msft_lib_proxy.cpp} (83%) diff --git a/docs/PRO_DEF_FREE_DISPATCH.md b/docs/PRO_DEF_FREE_DISPATCH.md index a57614b..60d9617 100644 --- a/docs/PRO_DEF_FREE_DISPATCH.md +++ b/docs/PRO_DEF_FREE_DISPATCH.md @@ -36,7 +36,7 @@ struct dispatch_name { template struct accessor { friend R accessibility_func_name(accessor cv ref self, Args... args) noex { - return pro::proxy_invoke(pro::access_proxy(SELF), std::forward(args)...); + return pro::proxy_invoke(pro::access_proxy(SELF), std::forward(args)...); } }; }; diff --git a/docs/PRO_DEF_MEM_DISPATCH.md b/docs/PRO_DEF_MEM_DISPATCH.md index c4ef01f..1857974 100644 --- a/docs/PRO_DEF_MEM_DISPATCH.md +++ b/docs/PRO_DEF_MEM_DISPATCH.md @@ -39,7 +39,7 @@ struct dispatch_name { template struct accessor { R accessibility_func_name(Args... args) cv ref noex { - return pro::proxy_invoke(pro::access_proxy(SELF), std::forward(args)...); + return pro::proxy_invoke(pro::access_proxy(SELF), std::forward(args)...); } }; }; diff --git a/docs/access_proxy.md b/docs/access_proxy.md index 3342593..d9f2ded 100644 --- a/docs/access_proxy.md +++ b/docs/access_proxy.md @@ -55,7 +55,7 @@ int main() { pro::proxy& p2 = pro::access_proxy(a); std::cout << std::boolalpha << (&p == &p2) << "\n"; // Prints: "true" because access_proxy converts // an accessor back to the original proxy - auto result = pro::proxy_invoke(p2); + auto result = pro::proxy_invoke(p2); std::cout << result << "\n"; // Prints: "123" } ``` diff --git a/docs/conversion_dispatch/accessor.md b/docs/conversion_dispatch/accessor.md index 94246f9..de894b6 100644 --- a/docs/conversion_dispatch/accessor.md +++ b/docs/conversion_dispatch/accessor.md @@ -27,4 +27,4 @@ Let `SELF` be `std::forward(*this)`. `(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are trivial types, inherits all `accessor...` types and `using` their `operator T`. -`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an explicit (when `Expl` is `true`) or implicit (when `Expl` is `false`) `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(access_proxy(SELF))`. +`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an explicit (when `Expl` is `true`) or implicit (when `Expl` is `false`) `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(access_proxy(SELF))`. diff --git a/docs/operator_dispatch/accessor.md b/docs/operator_dispatch/accessor.md index 64eda38..6b9effc 100644 --- a/docs/operator_dispatch/accessor.md +++ b/docs/operator_dispatch/accessor.md @@ -39,7 +39,7 @@ struct accessor { } ``` -`(3)` Provides an `operator sop(Args...)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Args...)` is equivalent to `return proxy_invoke(access_proxy(SELF), std::forward(args)...)`. +`(3)` Provides an `operator sop(Args...)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Args...)` is equivalent to `return proxy_invoke(access_proxy(SELF), std::forward(args)...)`. ### `!` and `~` @@ -53,7 +53,7 @@ struct accessor { } ``` -`(4)` Provides an `operator sop()` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop()` is equivalent to `return proxy_invoke(access_proxy(SELF))`. +`(4)` Provides an `operator sop()` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop()` is equivalent to `return proxy_invoke(access_proxy(SELF))`. ### Assignment SOPs @@ -67,7 +67,7 @@ struct accessor { } ``` -`(4)` Provides an `operator sop(Arg)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Arg)` calls `proxy_invoke(access_proxy(SELF), std::forward(arg))` and returns `access_proxy(SELF)` when `C::is_direct` is `true`, or otherwise, returns `*access_proxy(SELF)` when `C::is_direct` is `false`. +`(4)` Provides an `operator sop(Arg)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Arg)` calls `proxy_invoke(access_proxy(SELF), std::forward(arg))` and returns `access_proxy(SELF)` when `C::is_direct` is `true`, or otherwise, returns `*access_proxy(SELF)` when `C::is_direct` is `false`. ## Right-Hand-Side Operand Specializations @@ -94,7 +94,7 @@ struct accessor { } ``` -`(7)` Provides a `friend operator sop(Arg arg, accessor cv ref)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor cv ref)` is equivalent to `return proxy_invoke(access_proxy(SELF), std::forward(arg))`. +`(7)` Provides a `friend operator sop(Arg arg, accessor cv ref)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor cv ref)` is equivalent to `return proxy_invoke(access_proxy(SELF), std::forward(arg))`. ### Assignment SOPs @@ -108,4 +108,4 @@ struct accessor { } ``` -`(8)` Provides a `friend operator sop(Arg arg, accessor cv ref)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor cv ref)` calls `proxy_invoke(access_proxy(SELF), std::forward(arg))` and returns `access_proxy(SELF)` when `C::is_direct` is `true`, or otherwise, returns `*access_proxy(SELF)` when `C::is_direct` is `false`. +`(8)` Provides a `friend operator sop(Arg arg, accessor cv ref)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor cv ref)` calls `proxy_invoke(access_proxy(SELF), std::forward(arg))` and returns `access_proxy(SELF)` when `C::is_direct` is `true`, or otherwise, returns `*access_proxy(SELF)` when `C::is_direct` is `false`. diff --git a/docs/proxy_invoke.md b/docs/proxy_invoke.md index 378a8c9..3495a92 100644 --- a/docs/proxy_invoke.md +++ b/docs/proxy_invoke.md @@ -1,22 +1,22 @@ # Function template `proxy_invoke` ```cpp -template +template /* see below */ proxy_invoke(proxy& p, Args&&... args); -template +template /* see below */ proxy_invoke(const proxy& p, Args&&... args); -template +template /* see below */ proxy_invoke(proxy&& p, Args&&... args); -template +template /* see below */ proxy_invoke(const proxy&& p, Args&&... args); ``` -Invokes a `proxy` with a specified convention type and arguments. `C` is required to be defined in `typename F::convention_types`. Overload resolution is performed among the overload types defined in `typename C::overload_types`. +Invokes a `proxy` with a specified convention type, an overload type, and arguments. `C` is required to be defined in `typename F::convention_types`. `O` is required to be defined in `typename C::overload_types`. -Let `ptr` be the contained value of `p` with the same cv ref-qualifiers, `O` be the matched overload type among the overload types defined in `typename C::overload_types`, `Args2...` be the argument types of `O`, `R` be the return type of `O`, +Let `ptr` be the contained value of `p` with the same cv ref-qualifiers, `Args2...` be the argument types of `O`, `R` be the return type of `O`, - if `C::is_direct` is `true`, let `v` be `std::forward(ptr)`, or otherwise, - if `C::is_direct` is `false`, let `v` be `*std::forward(ptr)`, @@ -55,7 +55,7 @@ int main() { std::cout << ToString(*p) << "\n"; // Invokes with accessor, prints: "123" using C = std::tuple_element_t<0u, Stringable::convention_types>; - std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" + std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" } ``` diff --git a/proxy.h b/proxy.h index e92e2fb..1c4e488 100644 --- a/proxy.h +++ b/proxy.h @@ -259,9 +259,6 @@ struct overload_traits_impl : applicable_traits { } } }; - struct resolver { - overload_traits_impl operator()(add_qualifier_t, Args...); - }; template static constexpr bool applicable_ptr = @@ -350,13 +347,8 @@ struct conv_traits_impl : inapplicable_traits {}; template requires(sizeof...(Os) > 0u && (overload_traits::applicable && ...)) struct conv_traits_impl : applicable_traits { - struct overload_resolver : overload_traits::resolver... - { using overload_traits::resolver::operator()...; }; using meta = composite_meta_impl ::template meta_provider>...>; - template - using matched_overload_traits = std::invoke_result_t< - overload_resolver, add_qualifier_t, Args...>; template static constexpr bool applicable_ptr = @@ -575,15 +567,14 @@ template struct proxy_helper { static inline const auto& get_meta(const proxy& p) noexcept { return *p.meta_.operator->(); } - template + template static decltype(auto) invoke(add_qualifier_t, Q> p, Args&&... args) { - using OverloadTraits = typename conv_traits - ::template matched_overload_traits; - auto dispatcher = p.meta_->template dispatcher_metatemplate dispatcher_meta ::template meta_provider> ::dispatcher; if constexpr (C::is_direct && - OverloadTraits::qualifier == qualifier_type::rv) { + overload_traits::qualifier == qualifier_type::rv) { meta_ptr_reset_guard guard{p.meta_}; return dispatcher(std::forward>(*p.ptr_), std::forward(args)...); @@ -808,26 +799,26 @@ class proxy : public details::facade_traits::direct_accessor { alignas(F::constraints.max_align) std::byte ptr_[F::constraints.max_size]; }; -template +template decltype(auto) proxy_invoke(proxy& p, Args&&... args) { return details::proxy_helper::template invoke< - C, details::qualifier_type::lv>(p, std::forward(args)...); + C, O, details::qualifier_type::lv>(p, std::forward(args)...); } -template +template decltype(auto) proxy_invoke(const proxy& p, Args&&... args) { return details::proxy_helper::template invoke< - C, details::qualifier_type::const_lv>(p, std::forward(args)...); + C, O, details::qualifier_type::const_lv>(p, std::forward(args)...); } -template +template decltype(auto) proxy_invoke(proxy&& p, Args&&... args) { return details::proxy_helper::template invoke< - C, details::qualifier_type::rv>( + C, O, details::qualifier_type::rv>( std::forward>(p), std::forward(args)...); } -template +template decltype(auto) proxy_invoke(const proxy&& p, Args&&... args) { return details::proxy_helper::template invoke< - C, details::qualifier_type::const_rv>( + C, O, details::qualifier_type::const_rv>( std::forward>(p), std::forward(args)...); } @@ -1167,7 +1158,7 @@ struct facade_impl { struct accessor() Q> { \ __VA_ARGS__ () Q { \ if (access_proxy(SELF).has_value()) { \ - return proxy_invoke(access_proxy(SELF)); \ + return proxy_invoke() Q>(access_proxy(SELF)); \ } \ return nullptr; \ } \ @@ -1323,13 +1314,14 @@ struct operator_dispatch; #define ___PRO_DEF_LHS_LEFT_OP_ACCESSOR(Q, SELF, ...) \ template \ struct accessor { \ - R __VA_ARGS__ () Q { return proxy_invoke(access_proxy(SELF)); } \ + R __VA_ARGS__ () Q \ + { return proxy_invoke(access_proxy(SELF)); } \ } #define ___PRO_DEF_LHS_ANY_OP_ACCESSOR(Q, SELF, ...) \ template \ struct accessor { \ R __VA_ARGS__ (Args... args) Q { \ - return proxy_invoke( \ + return proxy_invoke( \ access_proxy(SELF), std::forward(args)...); \ } \ } @@ -1367,7 +1359,7 @@ struct operator_dispatch; template \ struct accessor { \ friend R __VA_ARGS__ (Arg arg, SELF) NE { \ - return proxy_invoke( \ + return proxy_invoke( \ access_proxy(FW_SELF), std::forward(arg)); \ } \ } @@ -1394,7 +1386,8 @@ struct operator_dispatch; template \ struct accessor { \ decltype(auto) __VA_ARGS__ (Arg arg) Q { \ - proxy_invoke(access_proxy(SELF), std::forward(arg)); \ + proxy_invoke( \ + access_proxy(SELF), std::forward(arg)); \ if constexpr (C::is_direct) { \ return access_proxy(SELF); \ } else { \ @@ -1406,7 +1399,7 @@ struct operator_dispatch; template \ struct accessor { \ friend Arg& __VA_ARGS__ (Arg& arg, SELF) NE { \ - proxy_invoke(access_proxy(FW_SELF), arg); \ + proxy_invoke(access_proxy(FW_SELF), arg); \ return arg; \ } \ } @@ -1510,7 +1503,7 @@ struct operator_dispatch<"[]", false> { template \ struct accessor { \ explicit(Expl) __VA_ARGS__ () Q \ - { return proxy_invoke(access_proxy(SELF)); } \ + { return proxy_invoke(access_proxy(SELF)); } \ } template struct conversion_dispatch { @@ -1537,7 +1530,8 @@ struct conversion_dispatch { template \ struct accessor<__F, __C, __R(__Args...) __Q> { \ __R __VA_ARGS__ (__Args... __args) __Q { \ - return ::pro::proxy_invoke<__C>(::pro::access_proxy<__F>(__SELF), \ + return ::pro::proxy_invoke<__C, __R(__Args...) __Q>( \ + ::pro::access_proxy<__F>(__SELF), \ ::std::forward<__Args>(__args)...); \ } \ } @@ -1560,7 +1554,8 @@ struct conversion_dispatch { template \ struct accessor<__F, __C, __R(__Args...) __Q> { \ friend __R __VA_ARGS__ (__SELF, __Args... __args) __NE { \ - return ::pro::proxy_invoke<__C>(::pro::access_proxy<__F>(__FW_SELF), \ + return ::pro::proxy_invoke<__C, __R(__Args...) __Q>( \ + ::pro::access_proxy<__F>(__FW_SELF), \ ::std::forward<__Args>(__args)...); \ } \ } diff --git a/samples/access_proxy.cpp b/samples/access_proxy.cpp index 5342bc8..7beaea3 100644 --- a/samples/access_proxy.cpp +++ b/samples/access_proxy.cpp @@ -27,6 +27,6 @@ int main() { pro::proxy& p2 = pro::access_proxy(a); std::cout << std::boolalpha << (&p == &p2) << "\n"; // Prints: "true" because access_proxy converts // an accessor back to the original proxy - auto result = pro::proxy_invoke(p2); + auto result = pro::proxy_invoke(p2); std::cout << result << "\n"; // Prints: "123" } diff --git a/samples/__msft_lib_proxy.cpp b/samples/msft_lib_proxy.cpp similarity index 83% rename from samples/__msft_lib_proxy.cpp rename to samples/msft_lib_proxy.cpp index 2856db1..4bbb0d9 100644 --- a/samples/__msft_lib_proxy.cpp +++ b/samples/msft_lib_proxy.cpp @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -// This file contains example code from __msft_lib_proxy.md. +// This file contains example code from msft_lib_proxy.md. #include diff --git a/samples/proxy_invoke.cpp b/samples/proxy_invoke.cpp index 1385167..44197c2 100644 --- a/samples/proxy_invoke.cpp +++ b/samples/proxy_invoke.cpp @@ -19,5 +19,5 @@ int main() { std::cout << ToString(*p) << "\n"; // Invokes with accessor, prints: "123" using C = std::tuple_element_t<0u, Stringable::convention_types>; - std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" + std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" }