From e4597f398d874898a89d63db4447d8fe723213bc Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Sat, 20 Jun 2026 21:35:02 +0800 Subject: [PATCH 1/3] Update documentation --- CMakeLists.txt | 2 +- MODULE.bazel | 2 +- README.md | 6 +- docs/spec/.pages | 2 +- docs/spec/PRO_DEF_FREE_AS_MEM_DISPATCH.md | 2 +- docs/spec/PRO_DEF_FREE_DISPATCH.md | 2 +- docs/spec/PRO_DEF_MEM_DISPATCH.md | 2 +- docs/spec/ProAccessible.md | 2 +- docs/spec/README.md | 16 +++- docs/spec/basic_facade_builder/.pages | 1 + docs/spec/basic_facade_builder/README.md | 1 + docs/spec/basic_facade_builder/add_facade.md | 9 ++- .../add_facade_with_substitution.md | 53 +++++++++++++ .../basic_facade_builder/add_reflection.md | 4 +- .../explicit_conversion_dispatch/accessor.md | 2 +- .../implicit_conversion_dispatch/accessor.md | 2 +- docs/spec/msft_lib_proxy.md | 1 + docs/spec/operator_dispatch/accessor.md | 10 +-- docs/spec/proxy/.pages | 7 +- docs/spec/proxy/README.md | 3 + docs/spec/proxy/indirection.md | 2 +- docs/spec/proxy/invoke.md | 63 ++++++++++++++++ docs/spec/proxy/reflect.md | 75 +++++++++++++++++++ docs/spec/proxy/reinterpret_invoke.md | 60 +++++++++++++++ docs/spec/proxy_indirect_accessor.md | 27 ------- docs/spec/proxy_indirect_accessor/.pages | 5 ++ docs/spec/proxy_indirect_accessor/README.md | 34 +++++++++ docs/spec/proxy_indirect_accessor/invoke.md | 62 +++++++++++++++ docs/spec/proxy_indirect_accessor/reflect.md | 69 +++++++++++++++++ .../reinterpret_invoke.md | 60 +++++++++++++++ docs/spec/proxy_invoke.md | 4 + docs/spec/proxy_reflect.md | 4 + docs/spec/skills_rtti/README.md | 2 +- docs/spec/substitution_dispatch/accessor.md | 2 +- include/proxy/v4/proxy_macros.h | 2 +- meson.build | 2 +- 36 files changed, 543 insertions(+), 59 deletions(-) create mode 100644 docs/spec/basic_facade_builder/add_facade_with_substitution.md create mode 100644 docs/spec/proxy/invoke.md create mode 100644 docs/spec/proxy/reflect.md create mode 100644 docs/spec/proxy/reinterpret_invoke.md delete mode 100644 docs/spec/proxy_indirect_accessor.md create mode 100644 docs/spec/proxy_indirect_accessor/.pages create mode 100644 docs/spec/proxy_indirect_accessor/README.md create mode 100644 docs/spec/proxy_indirect_accessor/invoke.md create mode 100644 docs/spec/proxy_indirect_accessor/reflect.md create mode 100644 docs/spec/proxy_indirect_accessor/reinterpret_invoke.md diff --git a/CMakeLists.txt b/CMakeLists.txt index f01a29b..bc48900 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.28) -project(msft_proxy4 VERSION 4.0.2 LANGUAGES CXX) +project(msft_proxy4 VERSION 4.1.0 LANGUAGES CXX) add_library(msft_proxy4 INTERFACE) set_target_properties(msft_proxy4 PROPERTIES EXPORT_NAME proxy) add_library(msft_proxy4::proxy ALIAS msft_proxy4) diff --git a/MODULE.bazel b/MODULE.bazel index 3b5a60d..fe60226 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,6 +1,6 @@ module( name = "proxy", - version = "4.0.2", + version = "4.1.0", ) bazel_dep(name = "platforms", version = "1.1.0") diff --git a/README.md b/README.md index 336795c..53c335d 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ The "Proxy" library is a self-contained solution for runtime polymorphism in C++ - **Concepts**: To facilitate template programming with "Proxy", 3 concepts are exported from a facade type. Namely, [`proxiable`](https://ngcpp.github.io/proxy/spec/proxiable), [`proxiable_target`](https://ngcpp.github.io/proxy/spec/proxiable_target) and [`inplace_proxiable_target`](https://ngcpp.github.io/proxy/spec/inplace_proxiable_target). - **Allocator awareness**: [function template `allocate_proxy`](https://ngcpp.github.io/proxy/spec/allocate_proxy) is able to create a `proxy` from a value with any custom allocator. In C++11, [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function) and [`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task) had constructors that accepted custom allocators for performance tuning, but these were [removed in C++17](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0302r1.html) because "the semantics are unclear, and there are technical issues with storing an allocator in a type-erased context and then recovering that allocator later for any allocations needed during copy assignment". These issues do not apply to `allocate_proxy`. - **Configurable constraints**: [`facade_builder`](https://ngcpp.github.io/proxy/spec/basic_facade_builder) provides full support for constraints configuration, including memory layout (by [`restrict_layout`](https://ngcpp.github.io/proxy/spec/basic_facade_builder/restrict_layout)), copyability (by [`support_copy`](https://ngcpp.github.io/proxy/spec/basic_facade_builder/support_copy)), relocatability (by [`support_relocation`](https://ngcpp.github.io/proxy/spec/basic_facade_builder/support_relocation)), and destructibility (by [`support_destruction`](https://ngcpp.github.io/proxy/spec/basic_facade_builder/support_destruction)). -- **Reflection**: `proxy` supports type-based compile-time reflection for runtime queries. Please refer to [`facade_builder::add_reflection`](https://ngcpp.github.io/proxy/spec/basic_facade_builder/add_reflection) and [function template `proxy_reflect`](https://ngcpp.github.io/proxy/spec/proxy_reflect) for more details. +- **Reflection**: `proxy` supports type-based compile-time reflection for runtime queries. Please refer to [`facade_builder::add_reflection`](https://ngcpp.github.io/proxy/spec/basic_facade_builder/add_reflection) and [function template `reflect`](https://ngcpp.github.io/proxy/spec/proxy_indirect_accessor/reflect) for more details. - **Non-owning proxy**: Although `proxy` can manage the lifetime of an object effectively, similar to a smart pointer, we sometimes want to dereference it before passing to a non-owning context. This has been implemented as an extension since 3.2.0. Please refer to [function template `make_proxy_view`](https://ngcpp.github.io/proxy/spec/make_proxy_view), [alias template `proxy_view`, class template `observer_facade`](https://ngcpp.github.io/proxy/spec/proxy_view) and [`skills::as_view`](https://ngcpp.github.io/proxy/spec/skills_as_view) for more details. - **RTTI**: [RTTI (run-time type information)](https://en.wikipedia.org/wiki/Run-time_type_information) provides "weak" reflection capability in C++ since the last century. Although it is not as powerful as reflection in some other languages (like `Object.GetType()` in C# or `Object.getClass()` in Java), it offers the basic infrastructure for type-safe casting at runtime. Since 4.0.0, "RTTI for `proxy`" has been implemented as an extension and allows users to opt-in for each facade definition. Please refer to [`skills::rtti`](https://ngcpp.github.io/proxy/spec/skills_rtti) for more details. - **Shared and weak ownership**: Although `proxy` can be created from a [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr), extensions are available to create `proxy` objects with shared and weak ownership in a more efficient way since 3.3.0. Please refer to [function template `make_proxy_shared`](https://ngcpp.github.io/proxy/spec/make_proxy_shared), [`allocate_proxy_shared`](https://ngcpp.github.io/proxy/spec/allocate_proxy_shared), [alias template `weak_proxy`, class template `weak_facade`](https://ngcpp.github.io/proxy/spec/weak_proxy) and [`skills::as_weak`](https://ngcpp.github.io/proxy/spec/skills_as_weak) for more details. @@ -243,7 +243,7 @@ Fetch via [CPM](https://github.com/cpm-cmake/CPM.cmake) (a thin wrapper over CMa ```cmake CPMAddPackage( NAME msft_proxy4 - GIT_TAG 4.0.2 + GIT_TAG 4.1.0 GIT_REPOSITORY https://github.com/ngcpp/proxy.git ) @@ -259,7 +259,7 @@ Place a wrap file at `subprojects/proxy.wrap` and Meson will fetch the source au ```ini [wrap-git] url = https://github.com/ngcpp/proxy.git -revision = 4.0.2 +revision = 4.1.0 [provide] dependency_names = msft_proxy4 diff --git a/docs/spec/.pages b/docs/spec/.pages index 2b6247c..6e854a9 100644 --- a/docs/spec/.pages +++ b/docs/spec/.pages @@ -15,7 +15,7 @@ nav: - is_bitwise_trivially_relocatable: is_bitwise_trivially_relocatable.md - not_implemented: not_implemented.md - operator_dispatch: operator_dispatch - - proxy_indirect_accessor: proxy_indirect_accessor.md + - proxy_indirect_accessor: proxy_indirect_accessor - proxy_view
observer_facade: proxy_view.md - proxy: proxy - substitution_dispatch: substitution_dispatch diff --git a/docs/spec/PRO_DEF_FREE_AS_MEM_DISPATCH.md b/docs/spec/PRO_DEF_FREE_AS_MEM_DISPATCH.md index b7eca2e..8745fa7 100644 --- a/docs/spec/PRO_DEF_FREE_AS_MEM_DISPATCH.md +++ b/docs/spec/PRO_DEF_FREE_AS_MEM_DISPATCH.md @@ -42,7 +42,7 @@ struct dispatch_name { template struct accessor { R accessibility_func_name(Args... args) cv ref noex { - return pro::proxy_invoke(static_cast

>(*this), std::forward(args)...); + return invoke(static_cast

>(*this), std::forward(args)...); } }; } diff --git a/docs/spec/PRO_DEF_FREE_DISPATCH.md b/docs/spec/PRO_DEF_FREE_DISPATCH.md index ded5483..0bdca88 100644 --- a/docs/spec/PRO_DEF_FREE_DISPATCH.md +++ b/docs/spec/PRO_DEF_FREE_DISPATCH.md @@ -39,7 +39,7 @@ struct dispatch_name { template struct accessor { friend R accessibility_func_name(P cv self, Args... args) noex { - return pro::proxy_invoke(static_cast

>(self), std::forward(args)...); + return invoke(static_cast

>(self), std::forward(args)...); } }; } diff --git a/docs/spec/PRO_DEF_MEM_DISPATCH.md b/docs/spec/PRO_DEF_MEM_DISPATCH.md index 2f100e4..a53f86a 100644 --- a/docs/spec/PRO_DEF_MEM_DISPATCH.md +++ b/docs/spec/PRO_DEF_MEM_DISPATCH.md @@ -41,7 +41,7 @@ struct dispatch_name { template struct accessor { R accessibility_func_name(Args... args) cv ref noex { - return pro::proxy_invoke(static_cast

>(*this), std::forward(args)...); + return invoke(static_cast

>(*this), std::forward(args)...); } }; } diff --git a/docs/spec/ProAccessible.md b/docs/spec/ProAccessible.md index c261217..dafa117 100644 --- a/docs/spec/ProAccessible.md +++ b/docs/spec/ProAccessible.md @@ -9,4 +9,4 @@ A type `T` meets the *ProAccessible* requirements of types `Args...` if the foll ## See Also - [class template `proxy`](proxy/README.md) -- [class template `proxy_indirect_accessor`](proxy_indirect_accessor.md) +- [class template `proxy_indirect_accessor`](proxy_indirect_accessor/README.md) diff --git a/docs/spec/README.md b/docs/spec/README.md index 255903e..c5b9b5b 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -28,7 +28,7 @@ This document provides the API specifications for the C++ library Proxy (version | [`is_bitwise_trivially_relocatable`](is_bitwise_trivially_relocatable.md) | Specifies whether a type is bitwise trivially relocatable | | [`not_implemented` ](not_implemented.md) | Exception thrown by `weak_dispatch` for the default implementation | | [`operator_dispatch`](operator_dispatch/README.md) | Dispatch type for operator expressions with accessibility | -| [`proxy_indirect_accessor`](proxy_indirect_accessor.md) | Provides indirection accessibility for `proxy` | +| [`proxy_indirect_accessor`](proxy_indirect_accessor/README.md) | Provides indirection accessibility for `proxy` | | [`proxy_view`
`observer_facade`](proxy_view.md) | Non-owning `proxy` optimized for raw pointer types | | [`proxy`](proxy/README.md) | Wraps a pointer object matching specified facade | | [`substitution_dispatch`](substitution_dispatch/README.md) | Dispatch type for `proxy` substitution with accessibility | @@ -55,8 +55,18 @@ This document provides the API specifications for the C++ library Proxy (version | [`make_proxy_shared`](make_proxy_shared.md) | Creates a `proxy` object with shared ownership | | [`make_proxy_view`](make_proxy_view.md) | Creates a `proxy_view` object | | [`make_proxy`](make_proxy.md) | Creates a `proxy` object potentially with heap allocation | -| [`proxy_invoke`](proxy_invoke.md) | Invokes a `proxy` with a specified convention | -| [`proxy_reflect`](proxy_reflect.md) | Acquires reflection information of a contained type | +| [`proxy_invoke`](proxy_invoke.md) | (Deprecated since 4.1.0; use [`invoke`](proxy_indirect_accessor/invoke.md)) Invokes a `proxy` with a specified convention | +| [`proxy_reflect`](proxy_reflect.md) | (Deprecated since 4.1.0; use [`reflect`](proxy_indirect_accessor/reflect.md)) Acquires reflection information of a contained type | + +### Non-Member Functions + +The following are not namespace-scope functions; each is a non-member function of [`proxy`](proxy/README.md) and [`proxy_indirect_accessor`](proxy_indirect_accessor/README.md), found only via [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl). Each is documented separately for the two classes. + +| Name | For `proxy` | For `proxy_indirect_accessor` | +| -------------------- | ----------------------------------------------- | ----------------------------------------------------------------- | +| `invoke` | [direct](proxy/invoke.md) | [indirect](proxy_indirect_accessor/invoke.md) | +| `reflect` | [direct](proxy/reflect.md) | [indirect](proxy_indirect_accessor/reflect.md) | +| `reinterpret_invoke` | [direct](proxy/reinterpret_invoke.md) | [indirect](proxy_indirect_accessor/reinterpret_invoke.md) | ## Header `` diff --git a/docs/spec/basic_facade_builder/.pages b/docs/spec/basic_facade_builder/.pages index 4fbf58e..4ed3625 100644 --- a/docs/spec/basic_facade_builder/.pages +++ b/docs/spec/basic_facade_builder/.pages @@ -1,6 +1,7 @@ nav: - basic_facade_builder: README.md - add_convention
add_indirect_convention
add_direct_convention: add_convention.md + - add_facade_with_substitution: add_facade_with_substitution.md - add_facade: add_facade.md - add_reflection
add_indirect_reflection
add_direct_reflection: add_reflection.md - add_skill: add_skill.md diff --git a/docs/spec/basic_facade_builder/README.md b/docs/spec/basic_facade_builder/README.md index 2ee5ea2..50a7863 100644 --- a/docs/spec/basic_facade_builder/README.md +++ b/docs/spec/basic_facade_builder/README.md @@ -38,6 +38,7 @@ using facade_builder = | Name | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | | [`add_convention`
`add_indirect_convention`
`add_direct_convention`](add_convention.md) | Adds a convention to the template parameters | +| [`add_facade_with_substitution`](add_facade_with_substitution.md) | Adds a facade to the template parameters, together with [substitution](../substitution_dispatch/README.md) support | | [`add_facade`](add_facade.md) | Adds a facade to the template parameters | | [`add_reflection`
`add_indirect_reflection`
`add_direct_reflection`](add_reflection.md) | Adds a reflection to the template parameters | | [`add_skill`](add_skill.md) | Adds a custom skill | diff --git a/docs/spec/basic_facade_builder/add_facade.md b/docs/spec/basic_facade_builder/add_facade.md index 2d73b5a..07f4c10 100644 --- a/docs/spec/basic_facade_builder/add_facade.md +++ b/docs/spec/basic_facade_builder/add_facade.md @@ -14,11 +14,13 @@ The alias template `add_facade` of `basic_facade_builder`) is deprecated. Use [`add_facade_with_substitution`](add_facade_with_substitution.md)`` instead. The single-argument form `add_facade` is not affected. ## Example @@ -50,7 +52,7 @@ struct StringDictionary struct MutableStringDictionary : pro::facade_builder // - ::add_facade // + ::add_facade_with_substitution // ::add_convention // ::build {}; @@ -83,4 +85,5 @@ int main() { ## See Also +- [`add_facade_with_substitution`](add_facade_with_substitution.md) - [`build`](build.md) diff --git a/docs/spec/basic_facade_builder/add_facade_with_substitution.md b/docs/spec/basic_facade_builder/add_facade_with_substitution.md new file mode 100644 index 0000000..0cfa327 --- /dev/null +++ b/docs/spec/basic_facade_builder/add_facade_with_substitution.md @@ -0,0 +1,53 @@ +# `basic_facade_builder::add_facade_with_substitution` + +> Since: 4.1.0 + +```cpp +template +using add_facade_with_substitution = basic_facade_builder; +``` + +The alias template `add_facade_with_substitution` of `basic_facade_builder` is equivalent to [`add_facade`](add_facade.md)``, except that it always merges a direct convention of [`substitution_dispatch`](../substitution_dispatch/README.md) into `Cs`. This convention enables substitution from a `proxy` of the built [facade](../facade.md) to a `proxy`. + +## Notes + +`add_facade_with_substitution` was introduced in `4.1.0` as a replacement for the deprecated `add_facade` syntax. + +The substitution convention is helpful when an API requires backward compatibility, at the cost of potentially a slightly larger binary size. When substitution is not required, use [`add_facade`](add_facade.md) to guarantee minimal binary size in code generation. + +## Example + +```cpp +#include +#include + +#include + +PRO_DEF_MEM_DISPATCH(MemSize, size); +PRO_DEF_MEM_DISPATCH(MemClear, clear); + +struct Container : pro::facade_builder // + ::add_convention // + ::build {}; + +// A proxy can be substituted with a proxy. +struct ClearableContainer : pro::facade_builder // + ::add_facade_with_substitution // + ::add_convention // + ::build {}; + +int main() { + pro::proxy p1 = + pro::make_proxy>(10); + std::cout << p1->size() << "\n"; // Prints "10" + + // Substitution from an rvalue: ClearableContainer -> Container + pro::proxy p2 = std::move(p1); + std::cout << p2->size() << "\n"; // Prints "10" +} +``` + +## See Also + +- [`add_facade`](add_facade.md) +- [`build`](build.md) diff --git a/docs/spec/basic_facade_builder/add_reflection.md b/docs/spec/basic_facade_builder/add_reflection.md index 7076cc5..d34984d 100644 --- a/docs/spec/basic_facade_builder/add_reflection.md +++ b/docs/spec/basic_facade_builder/add_reflection.md @@ -46,12 +46,12 @@ public: template struct accessor { friend std::size_t SizeOf(const P& self) noexcept { - const LayoutReflector& refl = pro::proxy_reflect(self); + const LayoutReflector& refl = reflect(self); return refl.Size; } friend std::size_t AlignOf(const P& self) noexcept { - const LayoutReflector& refl = pro::proxy_reflect(self); + const LayoutReflector& refl = reflect(self); return refl.Align; } }; diff --git a/docs/spec/explicit_conversion_dispatch/accessor.md b/docs/spec/explicit_conversion_dispatch/accessor.md index 2bec72b..7a22671 100644 --- a/docs/spec/explicit_conversion_dispatch/accessor.md +++ b/docs/spec/explicit_conversion_dispatch/accessor.md @@ -25,4 +25,4 @@ struct accessor { `(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible, inherits all `accessor...` types and `using` their `operator return-type-of`. `return-type-of` denotes the *return type* of the overload type `O`. -`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an explicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(static_cast

>(*this))`. +`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an explicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return invoke(static_cast

>(*this))`. diff --git a/docs/spec/implicit_conversion_dispatch/accessor.md b/docs/spec/implicit_conversion_dispatch/accessor.md index cf871e5..15cadf3 100644 --- a/docs/spec/implicit_conversion_dispatch/accessor.md +++ b/docs/spec/implicit_conversion_dispatch/accessor.md @@ -25,4 +25,4 @@ struct accessor { `(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible, inherits all `accessor...` types and `using` their `operator return-type-of`. `return-type-of` denotes the *return type* of the overload type `O`. -`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an implicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(static_cast

>(*this))`. +`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an implicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return invoke(static_cast

>(*this))`. diff --git a/docs/spec/msft_lib_proxy.md b/docs/spec/msft_lib_proxy.md index 71612e6..31906cc 100644 --- a/docs/spec/msft_lib_proxy.md +++ b/docs/spec/msft_lib_proxy.md @@ -10,6 +10,7 @@ Starting with 3.0.0, Proxy ships a feature-test macro that encodes the library v | Version | Value of `__msft_lib_proxy` | | ------- | --------------------------- | +| 4.1.0 | `202606L` | | 4.0.2 | `202603L` | | 4.0.1 | `202510L` | | 4.0.0 | `202508L` | diff --git a/docs/spec/operator_dispatch/accessor.md b/docs/spec/operator_dispatch/accessor.md index d35d672..c4ea650 100644 --- a/docs/spec/operator_dispatch/accessor.md +++ b/docs/spec/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(static_cast

>(*this), 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 invoke(static_cast

>(*this), 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(static_cast

>(*this))`. +`(4)` Provides an `operator sop()` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop()` is equivalent to `return invoke(static_cast

>(*this))`. ### 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(static_cast

>(*this), std::forward(arg))` and returns `static_cast

>(*this)`. +`(4)` Provides an `operator sop(Arg)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Arg)` calls `invoke(static_cast

>(*this), std::forward(arg))` and returns `static_cast

>(*this)`. ## Right-Hand-Side Operand Specializations @@ -94,7 +94,7 @@ struct accessor { } ``` -`(7)` Provides a `friend operator sop(Arg arg, P cv self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, P cv self)` is equivalent to `return proxy_invoke(static_cast

>(self), std::forward(arg))`. +`(7)` Provides a `friend operator sop(Arg arg, P cv self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, P cv self)` is equivalent to `return invoke(static_cast

>(self), std::forward(arg))`. ### Assignment SOPs @@ -108,4 +108,4 @@ struct accessor { } ``` -`(8)` Provides a `friend operator sop(Arg arg, P cv self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, P cv self)` calls `proxy_invoke(static_cast

>(self), std::forward(arg))` and returns `static_cast

>(self)`. +`(8)` Provides a `friend operator sop(Arg arg, P cv self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, P cv self)` calls `invoke(static_cast

>(self), std::forward(arg))` and returns `static_cast

>(self)`. diff --git a/docs/spec/proxy/.pages b/docs/spec/proxy/.pages index d405fe7..c1bfcb8 100644 --- a/docs/spec/proxy/.pages +++ b/docs/spec/proxy/.pages @@ -3,10 +3,13 @@ nav: - (constructor): constructor.md - (destructor): destructor.md - emplace: emplace.md + - invoke (non-member): invoke.md - operator bool
has_value: operator_bool.md - operator->
operator*: indirection.md - - operator=: assignment.md - operator= (non-member): friend_operator_equality.md + - operator=: assignment.md + - reflect (non-member): reflect.md + - reinterpret_invoke (non-member): reinterpret_invoke.md - reset: reset.md - - swap: swap.md - swap (non-member): friend_swap.md + - swap: swap.md diff --git a/docs/spec/proxy/README.md b/docs/spec/proxy/README.md index 5335fdd..d08cc96 100644 --- a/docs/spec/proxy/README.md +++ b/docs/spec/proxy/README.md @@ -43,6 +43,9 @@ As per `facade`, `typename F::convention_types` shall be a [tuple-like](https | ------------------------------------------- | ------------------------------------------------------------ | | [`operator==`](friend_operator_equality.md) | compares a `proxy` with `nullptr` | | [`swap`](friend_swap.md) | overload the [`std::swap`](https://en.cppreference.com/w/cpp/algorithm/swap) algorithm | +| [`invoke`](invoke.md) | invokes a `proxy` with a specified convention | +| [`reflect`](reflect.md) | acquires reflection information of a contained type | +| [`reinterpret_invoke`](reinterpret_invoke.md) | invokes a dispatch on a `proxy` whose contained type is known statically | ## Comparing with Other Standard Polymorphic Wrappers diff --git a/docs/spec/proxy/indirection.md b/docs/spec/proxy/indirection.md index 4bcdf1f..a1dd8ef 100644 --- a/docs/spec/proxy/indirection.md +++ b/docs/spec/proxy/indirection.md @@ -58,4 +58,4 @@ int main() { ## See Also -- [class template `proxy_indirect_accessor`](../proxy_indirect_accessor.md) +- [class template `proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) diff --git a/docs/spec/proxy/invoke.md b/docs/spec/proxy/invoke.md new file mode 100644 index 0000000..35eb7d0 --- /dev/null +++ b/docs/spec/proxy/invoke.md @@ -0,0 +1,63 @@ +# Function template `invoke` (`proxy`) + +> Since: 4.1.0 + +```cpp +template +return-type-of invoke(proxy& p, Args&&... args); +template +return-type-of invoke(const proxy& p, Args&&... args); +template +return-type-of invoke(proxy&& p, Args&&... args); +template +return-type-of invoke(const proxy&& p, Args&&... args); +``` + +Invokes a `proxy` with a specified dispatch type `D`, an overload type `O`, and arguments, through a *direct* convention. Let `Args2...` be the argument types of `O`, `R` be the return type of `O`. `return-type-of` is `R`. + +Let `ptr` be the contained value of `p` with the same cv ref-qualifiers. Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), ptr, static_cast(args)...)`. The behavior is undefined if `p` does not contain a value. + +There shall be a convention type `Conv` defined in `typename F::convention_types` where + +- `Conv::is_direct` is `true`, and +- `typename Conv::dispatch_type` is `D`, and +- there shall be an overload type `O1` defined in `typename Conv::overload_types` where [`substituted-overload`](../ProOverload.md)`` is `O`. + +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy` is an associated class of the arguments. + +To invoke an *indirect* convention, use [`invoke`](../proxy_indirect_accessor/invoke.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). + +## Notes + +`invoke` was introduced in `4.1.0` as a replacement for the deprecated [`proxy_invoke`](../proxy_invoke.md). `proxy_invoke` is a namespace-scope function, while `invoke` is a non-member function of `proxy` found only via argument-dependent lookup. + +It is generally not recommended to call `invoke` directly. Using an [`accessor`](../ProAccessible.md) is usually a better option with easier and more descriptive syntax. + +## Example + +```cpp +#include +#include + +#include + +PRO_DEF_MEM_DISPATCH(MemUseCount, use_count); + +// A direct convention operates on the contained pointer itself. +struct SharedAware + : pro::facade_builder // + ::add_direct_convention // + ::build {}; + +int main() { + pro::proxy p = std::make_shared(123); + std::cout << p.use_count() << "\n"; // Invokes with accessor, prints: "1" + std::cout << invoke(p) + << "\n"; // Invokes with the non-member invoke, also prints: "1" +} +``` + +## See Also + +- [function template `reflect` (`proxy`)](reflect.md) +- [function template `reinterpret_invoke` (`proxy`)](reinterpret_invoke.md) diff --git a/docs/spec/proxy/reflect.md b/docs/spec/proxy/reflect.md new file mode 100644 index 0000000..099bdd0 --- /dev/null +++ b/docs/spec/proxy/reflect.md @@ -0,0 +1,75 @@ +# Function template `reflect` (`proxy`) + +> Since: 4.1.0 + +```cpp +template +const R& reflect(const proxy& p) noexcept; +``` + +Acquires reflection information of the contained type of a `proxy`, through a *direct* reflection. + +Let `P` be the contained type of `p`. Returns a `const` reference of `R` direct-non-list-initialized with [`std::in_place_type

`](https://en.cppreference.com/w/cpp/utility/in_place). The behavior is undefined if `p` does not contain a value. + +There shall be a reflection type `Refl` defined in `typename F::reflection_types` where + +- `Refl::is_direct` is `true`, and +- `typename Refl::reflector_type` is `R`. + +The reference obtained from `reflect()` may be invalidated if `p` is subsequently modified. + +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy` is an associated class of the arguments. + +To acquire an *indirect* reflection (deduced from the pointed-to type), use [`reflect`](../proxy_indirect_accessor/reflect.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). + +## Notes + +`reflect` was introduced in `4.1.0` as a replacement for the deprecated [`proxy_reflect`](../proxy_reflect.md). `proxy_reflect` is a namespace-scope function, while `reflect` is a non-member function of `proxy` found only via argument-dependent lookup. + +This function is useful when only metadata deduced from a type is needed. While [`invoke`](invoke.md) can also retrieve type metadata, `reflect` can generate more efficient code in this context. + +## Example + +```cpp +#include +#include +#include + +#include + +class CopyabilityReflector { +public: + template + constexpr explicit CopyabilityReflector(std::in_place_type_t) + : copyable_(std::is_copy_constructible_v) {} + + template + struct accessor { + bool IsCopyable() const noexcept { + const CopyabilityReflector& self = + reflect(static_cast(*this)); + return self.copyable_; + } + }; + +private: + bool copyable_; +}; + +struct CopyabilityAware : pro::facade_builder // + ::add_direct_reflection // + ::build {}; + +int main() { + pro::proxy p1 = std::make_unique(); + std::cout << std::boolalpha << p1.IsCopyable() << "\n"; // Prints "false" + + pro::proxy p2 = std::make_shared(); + std::cout << p2.IsCopyable() << "\n"; // Prints "true" +} +``` + +## See Also + +- [function template `invoke` (`proxy`)](invoke.md) +- [alias template `basic_facade_builder::add_reflection`](../basic_facade_builder/add_reflection.md) diff --git a/docs/spec/proxy/reinterpret_invoke.md b/docs/spec/proxy/reinterpret_invoke.md new file mode 100644 index 0000000..7ad3ecc --- /dev/null +++ b/docs/spec/proxy/reinterpret_invoke.md @@ -0,0 +1,60 @@ +# Function template `reinterpret_invoke` (`proxy`) + +> Since: 4.1.0 + +```cpp +template +R reinterpret_invoke(proxy& p, Args&&... args); +template +R reinterpret_invoke(const proxy& p, Args&&... args); +template +R reinterpret_invoke(proxy&& p, Args&&... args); +template +R reinterpret_invoke(const proxy&& p, Args&&... args); +``` + +Invokes a dispatch on the value contained in a `proxy`, reinterpreting the underlying storage as a caller-specified pointer type `P`. `D` is a dispatch type, `R` is the return type, and `Args...` are the argument types forwarded to the dispatch. + +Let `ptr` be the contained value of `p`, with the same cv ref-qualifiers as `p`. **The behavior is undefined unless `p` contains a value whose type is `P`.** Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), ptr, std::forward(args)...)`. + +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy` is an associated class of the arguments. To reinterpret-invoke through the pointed-to value, use [`reinterpret_invoke`](../proxy_indirect_accessor/reinterpret_invoke.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). + +## Notes + +`reinterpret_invoke` is a low-level primitive. In contrast to [`invoke`](invoke.md), it performs **no type erasure**: it neither consults the runtime metadata of the `proxy` nor requires `D` to correspond to a convention registered in `typename F::convention_types`. Instead, the caller names the exact contained pointer type `P`, and the implementation reinterprets the `proxy`'s storage as `P` directly. This avoids the indirection of a virtual call, at the cost of requiring the contained type to be known statically — supplying a `P` that does not match the contained value is undefined behavior. + +For ordinary use, prefer an [`accessor`](../ProAccessible.md) or [`invoke`](invoke.md), which are type-erased and do not require the caller to know the contained type. `reinterpret_invoke` is intended for advanced scenarios, such as implementing custom dispatch types or [accessors](../ProAccessible.md), where the concrete pointer type is already known. + +## Example + +```cpp +#include +#include + +#include + +PRO_DEF_MEM_DISPATCH(MemUseCount, use_count); + +struct SharedAware + : pro::facade_builder // + ::add_direct_convention // + ::build {}; + +int main() { + pro::proxy p = + std::make_shared(123); // The contained pointer type is shared_ptr + + // Type-erased invocation via the runtime metadata of `p`: + std::cout << invoke(p) << "\n"; // "1" + + // Low-level invocation: we already know `p` holds a `std::shared_ptr`, + // so reinterpret the storage and dispatch directly, with no virtual call: + std::cout << reinterpret_invoke, MemUseCount, long>(p) + << "\n"; // Also prints "1" +} +``` + +## See Also + +- [function template `invoke` (`proxy`)](invoke.md) +- [named requirements *ProDispatch*](../ProDispatch.md) diff --git a/docs/spec/proxy_indirect_accessor.md b/docs/spec/proxy_indirect_accessor.md deleted file mode 100644 index ddb4c2a..0000000 --- a/docs/spec/proxy_indirect_accessor.md +++ /dev/null @@ -1,27 +0,0 @@ -# Class template `proxy_indirect_accessor` - -> Header: `proxy.h` -> Module: `proxy` -> Namespace: `pro::inline v4` -> Since: 3.2.0 - -```cpp -template -class proxy_indirect_accessor; -``` - -Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. As per `facade`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. - -- For each type `C` in `Cs`, if `C::is_direct` is `false` and `typename C::dispatch_type` meets the [*ProAccessible* requirements](ProAccessible.md) of `proxy_indirect_accessor, typename C::dispatch_type, substituted-overload-types...`, `typename C::dispatch_type::template accessor, typename C::dispatch_type, substituted-overload-types...>` is inherited by `proxy_indirect_accessor`. Let `Os...` be the element types of `typename C::overload_types`, `substituted-overload-types...` is [`substituted-overload...`](ProOverload.md). -- For each type `R` in `Rs`, if `R::is_direct` is `false` and `typename R::reflector_type` meets the [*ProAccessible* requirements](ProAccessible.md) of `proxy_indirect_accessor, typename R::reflector_type`, `typename R::reflector_type::template accessor, typename R::reflector_type` is inherited by `proxy_indirect_accessor`. - -## Member Functions - -| Name | Description | -| ----------------------- | ----------------------------------------- | -| (constructor) [deleted] | Has neither default nor copy constructors | - -## See also - -- [function template `proxy_invoke`](proxy_invoke.md) -- [function template `proxy_reflect`](proxy_reflect.md) diff --git a/docs/spec/proxy_indirect_accessor/.pages b/docs/spec/proxy_indirect_accessor/.pages new file mode 100644 index 0000000..58bb8a4 --- /dev/null +++ b/docs/spec/proxy_indirect_accessor/.pages @@ -0,0 +1,5 @@ +nav: + - proxy_indirect_accessor: README.md + - invoke: invoke.md + - reflect: reflect.md + - reinterpret_invoke: reinterpret_invoke.md diff --git a/docs/spec/proxy_indirect_accessor/README.md b/docs/spec/proxy_indirect_accessor/README.md new file mode 100644 index 0000000..cd3ac0d --- /dev/null +++ b/docs/spec/proxy_indirect_accessor/README.md @@ -0,0 +1,34 @@ +# Class template `proxy_indirect_accessor` + +> Header: `proxy.h` +> Module: `proxy` +> Namespace: `pro::inline v4` +> Since: 3.2.0 + +```cpp +template +class proxy_indirect_accessor; +``` + +Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. As per `facade`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. + +- For each type `C` in `Cs`, if `C::is_direct` is `false` and `typename C::dispatch_type` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy_indirect_accessor, typename C::dispatch_type, substituted-overload-types...`, `typename C::dispatch_type::template accessor, typename C::dispatch_type, substituted-overload-types...>` is inherited by `proxy_indirect_accessor`. Let `Os...` be the element types of `typename C::overload_types`, `substituted-overload-types...` is [`substituted-overload...`](../ProOverload.md). +- For each type `R` in `Rs`, if `R::is_direct` is `false` and `typename R::reflector_type` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy_indirect_accessor, typename R::reflector_type`, `typename R::reflector_type::template accessor, typename R::reflector_type` is inherited by `proxy_indirect_accessor`. + +## Member Functions + +| Name | Description | +| ----------------------- | ----------------------------------------- | +| (constructor) [deleted] | Has neither default nor copy constructors | + +## Non-Member Functions + +| Name | Description | +| --------------------------------------------- | ------------------------------------------------------------ | +| [`invoke`](invoke.md) | invokes a `proxy` with a specified convention | +| [`reflect`](reflect.md) | acquires reflection information of a contained type | +| [`reinterpret_invoke`](reinterpret_invoke.md) | invokes a dispatch on a `proxy` whose contained type is known statically | + +## See also + +- [class template `proxy`](../proxy/README.md) diff --git a/docs/spec/proxy_indirect_accessor/invoke.md b/docs/spec/proxy_indirect_accessor/invoke.md new file mode 100644 index 0000000..32204ef --- /dev/null +++ b/docs/spec/proxy_indirect_accessor/invoke.md @@ -0,0 +1,62 @@ +# Function template `invoke` (`proxy_indirect_accessor`) + +> Since: 4.1.0 + +```cpp +template +return-type-of invoke(proxy_indirect_accessor& p, Args&&... args); +template +return-type-of invoke(const proxy_indirect_accessor& p, Args&&... args); +template +return-type-of invoke(proxy_indirect_accessor&& p, Args&&... args); +template +return-type-of invoke(const proxy_indirect_accessor&& p, Args&&... args); +``` + +Invokes a `proxy_indirect_accessor` with a specified dispatch type `D`, an overload type `O`, and arguments, through an *indirect* convention. Let `Args2...` be the argument types of `O`, `R` be the return type of `O`. `return-type-of` is `R`. + +Let `ptr` be the contained value of the `proxy` object associated to `p` with the same cv ref-qualifiers. Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), *ptr, static_cast(args)...)`. + +There shall be a convention type `Conv` defined in `typename F::convention_types` where + +- `Conv::is_direct` is `false`, and +- `typename Conv::dispatch_type` is `D`, and +- there shall be an overload type `O1` defined in `typename Conv::overload_types` where [`substituted-overload`](../ProOverload.md)`` is `O`. + +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy_indirect_accessor` is an associated class of the arguments. + +A `proxy_indirect_accessor` is obtained by dereferencing a [`proxy`](../proxy/README.md) (i.e., `*p`). To invoke a *direct* convention, use [`invoke`](../proxy/invoke.md) on the [`proxy`](../proxy/README.md) itself. + +## Notes + +`invoke` was introduced in `4.1.0` as a replacement for the deprecated [`proxy_invoke`](../proxy_invoke.md). `proxy_invoke` is a namespace-scope function, while `invoke` is a non-member function of `proxy_indirect_accessor` found only via argument-dependent lookup. + +It is generally not recommended to call `invoke` directly. Using an [`accessor`](../ProAccessible.md) is usually a better option with easier and more descriptive syntax. + +## Example + +```cpp +#include +#include + +#include + +PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); + +struct Stringable : pro::facade_builder // + ::add_convention // + ::build {}; + +int main() { + int a = 123; + pro::proxy p = &a; + std::cout << ToString(*p) << "\n"; // Invokes with accessor, prints: "123" + std::cout << invoke(*p) + << "\n"; // Invokes with the non-member invoke, also prints: "123" +} +``` + +## See Also + +- [function template `reflect` (`proxy_indirect_accessor`)](reflect.md) +- [function template `reinterpret_invoke` (`proxy_indirect_accessor`)](reinterpret_invoke.md) diff --git a/docs/spec/proxy_indirect_accessor/reflect.md b/docs/spec/proxy_indirect_accessor/reflect.md new file mode 100644 index 0000000..547a2dc --- /dev/null +++ b/docs/spec/proxy_indirect_accessor/reflect.md @@ -0,0 +1,69 @@ +# Function template `reflect` (`proxy_indirect_accessor`) + +> Since: 4.1.0 + +```cpp +template +const R& reflect(const proxy_indirect_accessor& p) noexcept; +``` + +Acquires reflection information of the contained type of the associated `proxy`, through an *indirect* reflection. + +Let `P` be the contained type of the `proxy` object associated to `p`. Returns a `const` reference of `R` direct-non-list-initialized with [`std::in_place_type::element_type>`](https://en.cppreference.com/w/cpp/utility/in_place). + +There shall be a reflection type `Refl` defined in `typename F::reflection_types` where + +- `Refl::is_direct` is `false`, and +- `typename Refl::reflector_type` is `R`. + +The reference obtained from `reflect()` may be invalidated if the associated `proxy` is subsequently modified. + +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy_indirect_accessor` is an associated class of the arguments. + +A `proxy_indirect_accessor` is obtained by dereferencing a [`proxy`](../proxy/README.md) (i.e., `*p`). To acquire a *direct* reflection (deduced from the pointer type), use [`reflect`](../proxy/reflect.md) on the [`proxy`](../proxy/README.md) itself. + +## Notes + +`reflect` was introduced in `4.1.0` as a replacement for the deprecated [`proxy_reflect`](../proxy_reflect.md). `proxy_reflect` is a namespace-scope function, while `reflect` is a non-member function of `proxy_indirect_accessor` found only via argument-dependent lookup. + +This function is useful when only metadata deduced from a type is needed. While [`invoke`](invoke.md) can also retrieve type metadata, `reflect` can generate more efficient code in this context. + +## Example + +```cpp +#include + +#include + +class LayoutReflector { +public: + template + constexpr explicit LayoutReflector(std::in_place_type_t) + : Size(sizeof(T)), Align(alignof(T)) {} + + template + struct accessor { + friend std::size_t SizeOf(const P& self) noexcept { + const LayoutReflector& refl = reflect(self); + return refl.Size; + } + }; + + std::size_t Size, Align; +}; + +struct LayoutAware : pro::facade_builder // + ::add_indirect_reflection // + ::build {}; + +int main() { + int a = 123; + pro::proxy p = &a; + std::cout << SizeOf(*p) << "\n"; // Prints sizeof(int), the pointed-to type +} +``` + +## See Also + +- [function template `invoke` (`proxy_indirect_accessor`)](invoke.md) +- [alias template `basic_facade_builder::add_reflection`](../basic_facade_builder/add_reflection.md) diff --git a/docs/spec/proxy_indirect_accessor/reinterpret_invoke.md b/docs/spec/proxy_indirect_accessor/reinterpret_invoke.md new file mode 100644 index 0000000..d1bcf89 --- /dev/null +++ b/docs/spec/proxy_indirect_accessor/reinterpret_invoke.md @@ -0,0 +1,60 @@ +# Function template `reinterpret_invoke` (`proxy_indirect_accessor`) + +> Since: 4.1.0 + +```cpp +template +R reinterpret_invoke(proxy_indirect_accessor& p, Args&&... args); +template +R reinterpret_invoke(const proxy_indirect_accessor& p, Args&&... args); +template +R reinterpret_invoke(proxy_indirect_accessor&& p, Args&&... args); +template +R reinterpret_invoke(const proxy_indirect_accessor&& p, Args&&... args); +``` + +Invokes a dispatch on the value contained in the associated `proxy`, reinterpreting the underlying storage as a caller-specified pointer type `P`. `D` is a dispatch type, `R` is the return type, and `Args...` are the argument types forwarded to the dispatch. + +Let `ptr` be the contained value of the `proxy` object associated to `p`, with the same cv ref-qualifiers as `p`. **The behavior is undefined unless the associated `proxy` contains a value whose type is `P`.** Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), *ptr, std::forward(args)...)`. + +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy_indirect_accessor` is an associated class of the arguments. To reinterpret-invoke on the contained pointer itself, use [`reinterpret_invoke`](../proxy/reinterpret_invoke.md) on the [`proxy`](../proxy/README.md). + +## Notes + +`reinterpret_invoke` is a low-level primitive. In contrast to [`invoke`](invoke.md), it performs **no type erasure**: it neither consults the runtime metadata of the `proxy` nor requires `D` to correspond to a convention registered in `typename F::convention_types`. Instead, the caller names the exact contained pointer type `P`, and the implementation reinterprets the `proxy`'s storage as `P` directly. This avoids the indirection of a virtual call, at the cost of requiring the contained type to be known statically. Supplying a `P` that does not match the contained value is undefined behavior. + +For ordinary use, prefer an [`accessor`](../ProAccessible.md) or [`invoke`](invoke.md), which are type-erased and do not require the caller to know the contained type. `reinterpret_invoke` is intended for advanced scenarios, such as implementing custom dispatch types or [accessors](../ProAccessible.md), where the concrete pointer type is already known. + +## Example + +```cpp +#include +#include + +#include + +PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); + +struct Stringable : pro::facade_builder // + ::add_convention // + ::build {}; + +int main() { + int a = 123; + pro::proxy p = &a; // The contained pointer type is `int*` + + // Type-erased invocation via the runtime metadata of the associated proxy: + std::cout << invoke(*p) << "\n"; // "123" + + // Low-level invocation: we already know the proxy holds an `int*`, so + // reinterpret the storage as `int*` and dispatch directly, with no virtual + // call. The dispatch receives the pointed-to `int`: + std::cout << reinterpret_invoke(*p) + << "\n"; // Also prints "123" +} +``` + +## See Also + +- [function template `invoke` (`proxy_indirect_accessor`)](invoke.md) +- [named requirements *ProDispatch*](../ProDispatch.md) diff --git a/docs/spec/proxy_invoke.md b/docs/spec/proxy_invoke.md index c048784..98fb459 100644 --- a/docs/spec/proxy_invoke.md +++ b/docs/spec/proxy_invoke.md @@ -4,6 +4,8 @@ > Module: `proxy` > Namespace: `pro::inline v4` +> **Deprecated since 4.1.0**: Use the non-member `invoke` of [`proxy`](proxy/invoke.md) (for `(2)`) or [`proxy_indirect_accessor`](proxy_indirect_accessor/invoke.md) (for `(1)`) instead. Each overload of `proxy_invoke` is marked `[[deprecated]]` and forwards to the corresponding overload of `invoke`. `proxy_invoke` is retained for backward compatibility and may be removed in a future major release. + ```cpp // (1) template @@ -69,4 +71,6 @@ int main() { ## See Also +- [function template `invoke` (`proxy`)](proxy/invoke.md) +- [function template `invoke` (`proxy_indirect_accessor`)](proxy_indirect_accessor/invoke.md) - [function template `proxy_reflect`](proxy_reflect.md) diff --git a/docs/spec/proxy_reflect.md b/docs/spec/proxy_reflect.md index 918ee9d..06c40db 100644 --- a/docs/spec/proxy_reflect.md +++ b/docs/spec/proxy_reflect.md @@ -4,6 +4,8 @@ > Module: `proxy` > Namespace: `pro::inline v4` +> **Deprecated since 4.1.0**: Use the non-member `reflect` of [`proxy`](proxy/reflect.md) (for `(2)`) or [`proxy_indirect_accessor`](proxy_indirect_accessor/reflect.md) (for `(1)`) instead. Each overload of `proxy_reflect` is marked `[[deprecated]]` and forwards to the corresponding overload of `reflect`. `proxy_reflect` is retained for backward compatibility and may be removed in a future major release. + ```cpp // (1) template @@ -68,5 +70,7 @@ int main() { ## See Also +- [function template `reflect` (`proxy`)](proxy/reflect.md) +- [function template `reflect` (`proxy_indirect_accessor`)](proxy_indirect_accessor/reflect.md) - [alias template `basic_facade_builder::add_reflection`](basic_facade_builder/add_reflection.md) - [named requirements *ProReflection*](ProReflection.md) diff --git a/docs/spec/skills_rtti/README.md b/docs/spec/skills_rtti/README.md index 118f3a1..9b4afbd 100644 --- a/docs/spec/skills_rtti/README.md +++ b/docs/spec/skills_rtti/README.md @@ -16,7 +16,7 @@ template using rtti = indirect_rtti; ``` -The alias templates `rtti`, `indirect_rtti`, and `direct_rtti` modify a specialization of [`basic_facade_builder`](../basic_facade_builder/README.md), enabling [RTTI](https://en.wikipedia.org/wiki/Run-time_type_information) support for [`proxy`](../proxy/README.md), where `F` is a built [facade](../facade.md) type. For an RTTI-enabled facade `F`, non-member functions `proxy_typeid` (similar to [`std::any::type`](https://en.cppreference.com/w/cpp/utility/any/type)) and `proxy_cast` (similar to [`std::any_cast`](https://en.cppreference.com/w/cpp/utility/any/any_cast)) are available for [`proxy_indirect_accessor`](../proxy_indirect_accessor.md) (for `rtti` and `indirect_rtti`) or [`proxy`](../proxy/README.md) (for `direct_rtti`). +The alias templates `rtti`, `indirect_rtti`, and `direct_rtti` modify a specialization of [`basic_facade_builder`](../basic_facade_builder/README.md), enabling [RTTI](https://en.wikipedia.org/wiki/Run-time_type_information) support for [`proxy`](../proxy/README.md), where `F` is a built [facade](../facade.md) type. For an RTTI-enabled facade `F`, non-member functions `proxy_typeid` (similar to [`std::any::type`](https://en.cppreference.com/w/cpp/utility/any/type)) and `proxy_cast` (similar to [`std::any_cast`](https://en.cppreference.com/w/cpp/utility/any/any_cast)) are available for [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (for `rtti` and `indirect_rtti`) or [`proxy`](../proxy/README.md) (for `direct_rtti`). ## Non-Member Functions diff --git a/docs/spec/substitution_dispatch/accessor.md b/docs/spec/substitution_dispatch/accessor.md index e83fa00..05f71b3 100644 --- a/docs/spec/substitution_dispatch/accessor.md +++ b/docs/spec/substitution_dispatch/accessor.md @@ -25,4 +25,4 @@ struct accessor() cv ref noex> { `(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible, inherits all `accessor...` types and `using` their `operator return-type-of`. `return-type-of` denotes the *return type* of the overload type `O`. -`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `proxy() cv ref noex`, provides an implicit `operator proxy()` with the same *cv ref noex* specifiers. `accessor::operator proxy()` is equivalent to `return proxy_invoke() cv ref noex>(static_cast

>(*this))` when `static_cast(*this).has_value()` is `true`, or `return nullptr` otherwise. +`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `proxy() cv ref noex`, provides an implicit `operator proxy()` with the same *cv ref noex* specifiers. `accessor::operator proxy()` is equivalent to `return invoke() cv ref noex>(static_cast

>(*this))` when `static_cast(*this).has_value()` is `true`, or `return nullptr` otherwise. diff --git a/include/proxy/v4/proxy_macros.h b/include/proxy/v4/proxy_macros.h index e50dd51..91cd07e 100644 --- a/include/proxy/v4/proxy_macros.h +++ b/include/proxy/v4/proxy_macros.h @@ -29,7 +29,7 @@ #define PRO4D_DEBUG(...) __VA_ARGS__ #endif // NDEBUG -#define __msft_lib_proxy4 202603L +#define __msft_lib_proxy4 202606L #define PRO4D_DIRECT_FUNC_IMPL(...) \ noexcept(noexcept(__VA_ARGS__)) \ diff --git a/meson.build b/meson.build index 26acf94..297c868 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'msft_proxy4', 'cpp', - version: '4.0.2', + version: '4.1.0', license: 'MIT', license_files: 'LICENSE', meson_version: '>=1.3', From 894b1209e6599792fe6fb3363f9f33b37349b628 Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Sat, 20 Jun 2026 21:52:36 +0800 Subject: [PATCH 2/3] Rename targets --- docs/spec/README.md | 14 ++------------ docs/spec/proxy/.pages | 6 +++--- docs/spec/proxy/README.md | 14 +++++++------- docs/spec/proxy/{invoke.md => friend_invoke.md} | 6 +++--- docs/spec/proxy/{reflect.md => friend_reflect.md} | 6 +++--- ...pret_invoke.md => friend_reinterpret_invoke.md} | 8 ++++---- docs/spec/proxy_indirect_accessor/.pages | 6 +++--- docs/spec/proxy_indirect_accessor/README.md | 10 +++++----- .../{invoke.md => friend_invoke.md} | 6 +++--- .../{reflect.md => friend_reflect.md} | 6 +++--- ...pret_invoke.md => friend_reinterpret_invoke.md} | 8 ++++---- docs/spec/proxy_invoke.md | 6 +++--- docs/spec/proxy_reflect.md | 6 +++--- 13 files changed, 46 insertions(+), 56 deletions(-) rename docs/spec/proxy/{invoke.md => friend_invoke.md} (90%) rename docs/spec/proxy/{reflect.md => friend_reflect.md} (87%) rename docs/spec/proxy/{reinterpret_invoke.md => friend_reinterpret_invoke.md} (70%) rename docs/spec/proxy_indirect_accessor/{invoke.md => friend_invoke.md} (93%) rename docs/spec/proxy_indirect_accessor/{reflect.md => friend_reflect.md} (90%) rename docs/spec/proxy_indirect_accessor/{reinterpret_invoke.md => friend_reinterpret_invoke.md} (73%) diff --git a/docs/spec/README.md b/docs/spec/README.md index c5b9b5b..2d29469 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -55,18 +55,8 @@ This document provides the API specifications for the C++ library Proxy (version | [`make_proxy_shared`](make_proxy_shared.md) | Creates a `proxy` object with shared ownership | | [`make_proxy_view`](make_proxy_view.md) | Creates a `proxy_view` object | | [`make_proxy`](make_proxy.md) | Creates a `proxy` object potentially with heap allocation | -| [`proxy_invoke`](proxy_invoke.md) | (Deprecated since 4.1.0; use [`invoke`](proxy_indirect_accessor/invoke.md)) Invokes a `proxy` with a specified convention | -| [`proxy_reflect`](proxy_reflect.md) | (Deprecated since 4.1.0; use [`reflect`](proxy_indirect_accessor/reflect.md)) Acquires reflection information of a contained type | - -### Non-Member Functions - -The following are not namespace-scope functions; each is a non-member function of [`proxy`](proxy/README.md) and [`proxy_indirect_accessor`](proxy_indirect_accessor/README.md), found only via [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl). Each is documented separately for the two classes. - -| Name | For `proxy` | For `proxy_indirect_accessor` | -| -------------------- | ----------------------------------------------- | ----------------------------------------------------------------- | -| `invoke` | [direct](proxy/invoke.md) | [indirect](proxy_indirect_accessor/invoke.md) | -| `reflect` | [direct](proxy/reflect.md) | [indirect](proxy_indirect_accessor/reflect.md) | -| `reinterpret_invoke` | [direct](proxy/reinterpret_invoke.md) | [indirect](proxy_indirect_accessor/reinterpret_invoke.md) | +| [`proxy_invoke`](proxy_invoke.md) [deprecated] | Invokes a `proxy` with a specified convention | +| [`proxy_reflect`](proxy_reflect.md) [deprecated] | Acquires reflection information of a contained type | ## Header `` diff --git a/docs/spec/proxy/.pages b/docs/spec/proxy/.pages index c1bfcb8..17deb33 100644 --- a/docs/spec/proxy/.pages +++ b/docs/spec/proxy/.pages @@ -3,13 +3,13 @@ nav: - (constructor): constructor.md - (destructor): destructor.md - emplace: emplace.md - - invoke (non-member): invoke.md + - invoke (non-member): friend_invoke.md - operator bool
has_value: operator_bool.md - operator->
operator*: indirection.md - operator= (non-member): friend_operator_equality.md - operator=: assignment.md - - reflect (non-member): reflect.md - - reinterpret_invoke (non-member): reinterpret_invoke.md + - reflect (non-member): friend_reflect.md + - reinterpret_invoke (non-member): friend_reinterpret_invoke.md - reset: reset.md - swap (non-member): friend_swap.md - swap: swap.md diff --git a/docs/spec/proxy/README.md b/docs/spec/proxy/README.md index d08cc96..5e56583 100644 --- a/docs/spec/proxy/README.md +++ b/docs/spec/proxy/README.md @@ -39,13 +39,13 @@ As per `facade`, `typename F::convention_types` shall be a [tuple-like](https ## Non-Member Functions -| Name | Description | -| ------------------------------------------- | ------------------------------------------------------------ | -| [`operator==`](friend_operator_equality.md) | compares a `proxy` with `nullptr` | -| [`swap`](friend_swap.md) | overload the [`std::swap`](https://en.cppreference.com/w/cpp/algorithm/swap) algorithm | -| [`invoke`](invoke.md) | invokes a `proxy` with a specified convention | -| [`reflect`](reflect.md) | acquires reflection information of a contained type | -| [`reinterpret_invoke`](reinterpret_invoke.md) | invokes a dispatch on a `proxy` whose contained type is known statically | +| Name | Description | +| ---------------------------------------------------- | ------------------------------------------------------------ | +| [`operator==`](friend_operator_equality.md) | compares a `proxy` with `nullptr` | +| [`swap`](friend_swap.md) | overload the [`std::swap`](https://en.cppreference.com/w/cpp/algorithm/swap) algorithm | +| [`invoke`](friend_invoke.md) | invokes a `proxy` with a specified convention | +| [`reflect`](friend_reflect.md) | acquires reflection information of a contained type | +| [`reinterpret_invoke`](friend_reinterpret_invoke.md) | invokes a dispatch on a `proxy` whose contained type is known statically | ## Comparing with Other Standard Polymorphic Wrappers diff --git a/docs/spec/proxy/invoke.md b/docs/spec/proxy/friend_invoke.md similarity index 90% rename from docs/spec/proxy/invoke.md rename to docs/spec/proxy/friend_invoke.md index 35eb7d0..2e25c14 100644 --- a/docs/spec/proxy/invoke.md +++ b/docs/spec/proxy/friend_invoke.md @@ -25,7 +25,7 @@ There shall be a convention type `Conv` defined in `typename F::convention_types This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy` is an associated class of the arguments. -To invoke an *indirect* convention, use [`invoke`](../proxy_indirect_accessor/invoke.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). +To invoke an *indirect* convention, use [`invoke`](../proxy_indirect_accessor/friend_invoke.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). ## Notes @@ -59,5 +59,5 @@ int main() { ## See Also -- [function template `reflect` (`proxy`)](reflect.md) -- [function template `reinterpret_invoke` (`proxy`)](reinterpret_invoke.md) +- [function template `reflect` (`proxy`)](friend_reflect.md) +- [function template `reinterpret_invoke` (`proxy`)](friend_reinterpret_invoke.md) diff --git a/docs/spec/proxy/reflect.md b/docs/spec/proxy/friend_reflect.md similarity index 87% rename from docs/spec/proxy/reflect.md rename to docs/spec/proxy/friend_reflect.md index 099bdd0..ad66efc 100644 --- a/docs/spec/proxy/reflect.md +++ b/docs/spec/proxy/friend_reflect.md @@ -20,13 +20,13 @@ The reference obtained from `reflect()` may be invalidated if `p` is subsequentl This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy` is an associated class of the arguments. -To acquire an *indirect* reflection (deduced from the pointed-to type), use [`reflect`](../proxy_indirect_accessor/reflect.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). +To acquire an *indirect* reflection (deduced from the pointed-to type), use [`reflect`](../proxy_indirect_accessor/friend_reflect.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). ## Notes `reflect` was introduced in `4.1.0` as a replacement for the deprecated [`proxy_reflect`](../proxy_reflect.md). `proxy_reflect` is a namespace-scope function, while `reflect` is a non-member function of `proxy` found only via argument-dependent lookup. -This function is useful when only metadata deduced from a type is needed. While [`invoke`](invoke.md) can also retrieve type metadata, `reflect` can generate more efficient code in this context. +This function is useful when only metadata deduced from a type is needed. While [`invoke`](friend_invoke.md) can also retrieve type metadata, `reflect` can generate more efficient code in this context. ## Example @@ -71,5 +71,5 @@ int main() { ## See Also -- [function template `invoke` (`proxy`)](invoke.md) +- [function template `invoke` (`proxy`)](friend_invoke.md) - [alias template `basic_facade_builder::add_reflection`](../basic_facade_builder/add_reflection.md) diff --git a/docs/spec/proxy/reinterpret_invoke.md b/docs/spec/proxy/friend_reinterpret_invoke.md similarity index 70% rename from docs/spec/proxy/reinterpret_invoke.md rename to docs/spec/proxy/friend_reinterpret_invoke.md index 7ad3ecc..9278364 100644 --- a/docs/spec/proxy/reinterpret_invoke.md +++ b/docs/spec/proxy/friend_reinterpret_invoke.md @@ -17,13 +17,13 @@ Invokes a dispatch on the value contained in a `proxy`, reinterpreting the un Let `ptr` be the contained value of `p`, with the same cv ref-qualifiers as `p`. **The behavior is undefined unless `p` contains a value whose type is `P`.** Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), ptr, std::forward(args)...)`. -This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy` is an associated class of the arguments. To reinterpret-invoke through the pointed-to value, use [`reinterpret_invoke`](../proxy_indirect_accessor/reinterpret_invoke.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy` is an associated class of the arguments. To reinterpret-invoke through the pointed-to value, use [`reinterpret_invoke`](../proxy_indirect_accessor/friend_reinterpret_invoke.md) on the associated [`proxy_indirect_accessor`](../proxy_indirect_accessor/README.md) (i.e., on `*p`). ## Notes -`reinterpret_invoke` is a low-level primitive. In contrast to [`invoke`](invoke.md), it performs **no type erasure**: it neither consults the runtime metadata of the `proxy` nor requires `D` to correspond to a convention registered in `typename F::convention_types`. Instead, the caller names the exact contained pointer type `P`, and the implementation reinterprets the `proxy`'s storage as `P` directly. This avoids the indirection of a virtual call, at the cost of requiring the contained type to be known statically — supplying a `P` that does not match the contained value is undefined behavior. +`reinterpret_invoke` is a low-level primitive. In contrast to [`invoke`](friend_invoke.md), it performs **no type erasure**: it neither consults the runtime metadata of the `proxy` nor requires `D` to correspond to a convention registered in `typename F::convention_types`. Instead, the caller names the exact contained pointer type `P`, and the implementation reinterprets the `proxy`'s storage as `P` directly. This avoids the indirection of a virtual call, at the cost of requiring the contained type to be known statically — supplying a `P` that does not match the contained value is undefined behavior. -For ordinary use, prefer an [`accessor`](../ProAccessible.md) or [`invoke`](invoke.md), which are type-erased and do not require the caller to know the contained type. `reinterpret_invoke` is intended for advanced scenarios, such as implementing custom dispatch types or [accessors](../ProAccessible.md), where the concrete pointer type is already known. +For ordinary use, prefer an [`accessor`](../ProAccessible.md) or [`invoke`](friend_invoke.md), which are type-erased and do not require the caller to know the contained type. `reinterpret_invoke` is intended for advanced scenarios, such as implementing custom dispatch types or [accessors](../ProAccessible.md), where the concrete pointer type is already known. ## Example @@ -56,5 +56,5 @@ int main() { ## See Also -- [function template `invoke` (`proxy`)](invoke.md) +- [function template `invoke` (`proxy`)](friend_invoke.md) - [named requirements *ProDispatch*](../ProDispatch.md) diff --git a/docs/spec/proxy_indirect_accessor/.pages b/docs/spec/proxy_indirect_accessor/.pages index 58bb8a4..8ae8f61 100644 --- a/docs/spec/proxy_indirect_accessor/.pages +++ b/docs/spec/proxy_indirect_accessor/.pages @@ -1,5 +1,5 @@ nav: - proxy_indirect_accessor: README.md - - invoke: invoke.md - - reflect: reflect.md - - reinterpret_invoke: reinterpret_invoke.md + - invoke: friend_invoke.md + - reflect: friend_reflect.md + - reinterpret_invoke: friend_reinterpret_invoke.md diff --git a/docs/spec/proxy_indirect_accessor/README.md b/docs/spec/proxy_indirect_accessor/README.md index cd3ac0d..fbab8dc 100644 --- a/docs/spec/proxy_indirect_accessor/README.md +++ b/docs/spec/proxy_indirect_accessor/README.md @@ -23,11 +23,11 @@ Class template `proxy_indirect_accessor` provides indirection accessibility for ## Non-Member Functions -| Name | Description | -| --------------------------------------------- | ------------------------------------------------------------ | -| [`invoke`](invoke.md) | invokes a `proxy` with a specified convention | -| [`reflect`](reflect.md) | acquires reflection information of a contained type | -| [`reinterpret_invoke`](reinterpret_invoke.md) | invokes a dispatch on a `proxy` whose contained type is known statically | +| Name | Description | +| ---------------------------------------------------- | ------------------------------------------------------------ | +| [`invoke`](friend_invoke.md) | invokes a `proxy` with a specified convention | +| [`reflect`](friend_reflect.md) | acquires reflection information of a contained type | +| [`reinterpret_invoke`](friend_reinterpret_invoke.md) | invokes a dispatch on a `proxy` whose contained type is known statically | ## See also diff --git a/docs/spec/proxy_indirect_accessor/invoke.md b/docs/spec/proxy_indirect_accessor/friend_invoke.md similarity index 93% rename from docs/spec/proxy_indirect_accessor/invoke.md rename to docs/spec/proxy_indirect_accessor/friend_invoke.md index 32204ef..0a5e9f1 100644 --- a/docs/spec/proxy_indirect_accessor/invoke.md +++ b/docs/spec/proxy_indirect_accessor/friend_invoke.md @@ -25,7 +25,7 @@ There shall be a convention type `Conv` defined in `typename F::convention_types This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy_indirect_accessor` is an associated class of the arguments. -A `proxy_indirect_accessor` is obtained by dereferencing a [`proxy`](../proxy/README.md) (i.e., `*p`). To invoke a *direct* convention, use [`invoke`](../proxy/invoke.md) on the [`proxy`](../proxy/README.md) itself. +A `proxy_indirect_accessor` is obtained by dereferencing a [`proxy`](../proxy/README.md) (i.e., `*p`). To invoke a *direct* convention, use [`invoke`](../proxy/friend_invoke.md) on the [`proxy`](../proxy/README.md) itself. ## Notes @@ -58,5 +58,5 @@ int main() { ## See Also -- [function template `reflect` (`proxy_indirect_accessor`)](reflect.md) -- [function template `reinterpret_invoke` (`proxy_indirect_accessor`)](reinterpret_invoke.md) +- [function template `reflect` (`proxy_indirect_accessor`)](friend_reflect.md) +- [function template `reinterpret_invoke` (`proxy_indirect_accessor`)](friend_reinterpret_invoke.md) diff --git a/docs/spec/proxy_indirect_accessor/reflect.md b/docs/spec/proxy_indirect_accessor/friend_reflect.md similarity index 90% rename from docs/spec/proxy_indirect_accessor/reflect.md rename to docs/spec/proxy_indirect_accessor/friend_reflect.md index 547a2dc..474df8a 100644 --- a/docs/spec/proxy_indirect_accessor/reflect.md +++ b/docs/spec/proxy_indirect_accessor/friend_reflect.md @@ -20,13 +20,13 @@ The reference obtained from `reflect()` may be invalidated if the associated `pr This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy_indirect_accessor` is an associated class of the arguments. -A `proxy_indirect_accessor` is obtained by dereferencing a [`proxy`](../proxy/README.md) (i.e., `*p`). To acquire a *direct* reflection (deduced from the pointer type), use [`reflect`](../proxy/reflect.md) on the [`proxy`](../proxy/README.md) itself. +A `proxy_indirect_accessor` is obtained by dereferencing a [`proxy`](../proxy/README.md) (i.e., `*p`). To acquire a *direct* reflection (deduced from the pointer type), use [`reflect`](../proxy/friend_reflect.md) on the [`proxy`](../proxy/README.md) itself. ## Notes `reflect` was introduced in `4.1.0` as a replacement for the deprecated [`proxy_reflect`](../proxy_reflect.md). `proxy_reflect` is a namespace-scope function, while `reflect` is a non-member function of `proxy_indirect_accessor` found only via argument-dependent lookup. -This function is useful when only metadata deduced from a type is needed. While [`invoke`](invoke.md) can also retrieve type metadata, `reflect` can generate more efficient code in this context. +This function is useful when only metadata deduced from a type is needed. While [`invoke`](friend_invoke.md) can also retrieve type metadata, `reflect` can generate more efficient code in this context. ## Example @@ -65,5 +65,5 @@ int main() { ## See Also -- [function template `invoke` (`proxy_indirect_accessor`)](invoke.md) +- [function template `invoke` (`proxy_indirect_accessor`)](friend_invoke.md) - [alias template `basic_facade_builder::add_reflection`](../basic_facade_builder/add_reflection.md) diff --git a/docs/spec/proxy_indirect_accessor/reinterpret_invoke.md b/docs/spec/proxy_indirect_accessor/friend_reinterpret_invoke.md similarity index 73% rename from docs/spec/proxy_indirect_accessor/reinterpret_invoke.md rename to docs/spec/proxy_indirect_accessor/friend_reinterpret_invoke.md index d1bcf89..0d0ca6c 100644 --- a/docs/spec/proxy_indirect_accessor/reinterpret_invoke.md +++ b/docs/spec/proxy_indirect_accessor/friend_reinterpret_invoke.md @@ -17,13 +17,13 @@ Invokes a dispatch on the value contained in the associated `proxy`, reinterpret Let `ptr` be the contained value of the `proxy` object associated to `p`, with the same cv ref-qualifiers as `p`. **The behavior is undefined unless the associated `proxy` contains a value whose type is `P`.** Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), *ptr, std::forward(args)...)`. -This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy_indirect_accessor` is an associated class of the arguments. To reinterpret-invoke on the contained pointer itself, use [`reinterpret_invoke`](../proxy/reinterpret_invoke.md) on the [`proxy`](../proxy/README.md). +This function is not visible to ordinary [unqualified](https://en.cppreference.com/w/cpp/language/unqualified_lookup) or [qualified lookup](https://en.cppreference.com/w/cpp/language/qualified_lookup). It can only be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `proxy_indirect_accessor` is an associated class of the arguments. To reinterpret-invoke on the contained pointer itself, use [`reinterpret_invoke`](../proxy/friend_reinterpret_invoke.md) on the [`proxy`](../proxy/README.md). ## Notes -`reinterpret_invoke` is a low-level primitive. In contrast to [`invoke`](invoke.md), it performs **no type erasure**: it neither consults the runtime metadata of the `proxy` nor requires `D` to correspond to a convention registered in `typename F::convention_types`. Instead, the caller names the exact contained pointer type `P`, and the implementation reinterprets the `proxy`'s storage as `P` directly. This avoids the indirection of a virtual call, at the cost of requiring the contained type to be known statically. Supplying a `P` that does not match the contained value is undefined behavior. +`reinterpret_invoke` is a low-level primitive. In contrast to [`invoke`](friend_invoke.md), it performs **no type erasure**: it neither consults the runtime metadata of the `proxy` nor requires `D` to correspond to a convention registered in `typename F::convention_types`. Instead, the caller names the exact contained pointer type `P`, and the implementation reinterprets the `proxy`'s storage as `P` directly. This avoids the indirection of a virtual call, at the cost of requiring the contained type to be known statically. Supplying a `P` that does not match the contained value is undefined behavior. -For ordinary use, prefer an [`accessor`](../ProAccessible.md) or [`invoke`](invoke.md), which are type-erased and do not require the caller to know the contained type. `reinterpret_invoke` is intended for advanced scenarios, such as implementing custom dispatch types or [accessors](../ProAccessible.md), where the concrete pointer type is already known. +For ordinary use, prefer an [`accessor`](../ProAccessible.md) or [`invoke`](friend_invoke.md), which are type-erased and do not require the caller to know the contained type. `reinterpret_invoke` is intended for advanced scenarios, such as implementing custom dispatch types or [accessors](../ProAccessible.md), where the concrete pointer type is already known. ## Example @@ -56,5 +56,5 @@ int main() { ## See Also -- [function template `invoke` (`proxy_indirect_accessor`)](invoke.md) +- [function template `invoke` (`proxy_indirect_accessor`)](friend_invoke.md) - [named requirements *ProDispatch*](../ProDispatch.md) diff --git a/docs/spec/proxy_invoke.md b/docs/spec/proxy_invoke.md index 98fb459..dda3a2d 100644 --- a/docs/spec/proxy_invoke.md +++ b/docs/spec/proxy_invoke.md @@ -4,7 +4,7 @@ > Module: `proxy` > Namespace: `pro::inline v4` -> **Deprecated since 4.1.0**: Use the non-member `invoke` of [`proxy`](proxy/invoke.md) (for `(2)`) or [`proxy_indirect_accessor`](proxy_indirect_accessor/invoke.md) (for `(1)`) instead. Each overload of `proxy_invoke` is marked `[[deprecated]]` and forwards to the corresponding overload of `invoke`. `proxy_invoke` is retained for backward compatibility and may be removed in a future major release. +> **Deprecated since 4.1.0**: Use the non-member `invoke` of [`proxy`](proxy/friend_invoke.md) (for `(2)`) or [`proxy_indirect_accessor`](proxy_indirect_accessor/friend_invoke.md) (for `(1)`) instead. Each overload of `proxy_invoke` is marked `[[deprecated]]` and forwards to the corresponding overload of `invoke`. `proxy_invoke` is retained for backward compatibility and may be removed in a future major release. ```cpp // (1) @@ -71,6 +71,6 @@ int main() { ## See Also -- [function template `invoke` (`proxy`)](proxy/invoke.md) -- [function template `invoke` (`proxy_indirect_accessor`)](proxy_indirect_accessor/invoke.md) +- [function template `invoke` (`proxy`)](proxy/friend_invoke.md) +- [function template `invoke` (`proxy_indirect_accessor`)](proxy_indirect_accessor/friend_invoke.md) - [function template `proxy_reflect`](proxy_reflect.md) diff --git a/docs/spec/proxy_reflect.md b/docs/spec/proxy_reflect.md index 06c40db..99ac8a7 100644 --- a/docs/spec/proxy_reflect.md +++ b/docs/spec/proxy_reflect.md @@ -4,7 +4,7 @@ > Module: `proxy` > Namespace: `pro::inline v4` -> **Deprecated since 4.1.0**: Use the non-member `reflect` of [`proxy`](proxy/reflect.md) (for `(2)`) or [`proxy_indirect_accessor`](proxy_indirect_accessor/reflect.md) (for `(1)`) instead. Each overload of `proxy_reflect` is marked `[[deprecated]]` and forwards to the corresponding overload of `reflect`. `proxy_reflect` is retained for backward compatibility and may be removed in a future major release. +> **Deprecated since 4.1.0**: Use the non-member `reflect` of [`proxy`](proxy/friend_reflect.md) (for `(2)`) or [`proxy_indirect_accessor`](proxy_indirect_accessor/friend_reflect.md) (for `(1)`) instead. Each overload of `proxy_reflect` is marked `[[deprecated]]` and forwards to the corresponding overload of `reflect`. `proxy_reflect` is retained for backward compatibility and may be removed in a future major release. ```cpp // (1) @@ -70,7 +70,7 @@ int main() { ## See Also -- [function template `reflect` (`proxy`)](proxy/reflect.md) -- [function template `reflect` (`proxy_indirect_accessor`)](proxy_indirect_accessor/reflect.md) +- [function template `reflect` (`proxy`)](proxy/friend_reflect.md) +- [function template `reflect` (`proxy_indirect_accessor`)](proxy_indirect_accessor/friend_reflect.md) - [alias template `basic_facade_builder::add_reflection`](basic_facade_builder/add_reflection.md) - [named requirements *ProReflection*](ProReflection.md) From bfc8b821f46065e017bb1cc739dce2f163a9002b Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Sat, 20 Jun 2026 21:56:55 +0800 Subject: [PATCH 3/3] Precommit --- .../spec/basic_facade_builder/add_facade_with_substitution.md | 2 +- docs/spec/proxy/friend_invoke.md | 4 ++-- docs/spec/proxy/friend_reinterpret_invoke.md | 4 ++-- docs/spec/proxy_indirect_accessor/friend_reflect.md | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/spec/basic_facade_builder/add_facade_with_substitution.md b/docs/spec/basic_facade_builder/add_facade_with_substitution.md index 0cfa327..93f90dc 100644 --- a/docs/spec/basic_facade_builder/add_facade_with_substitution.md +++ b/docs/spec/basic_facade_builder/add_facade_with_substitution.md @@ -31,7 +31,7 @@ struct Container : pro::facade_builder // ::build {}; // A proxy can be substituted with a proxy. -struct ClearableContainer : pro::facade_builder // +struct ClearableContainer : pro::facade_builder // ::add_facade_with_substitution // ::add_convention // ::build {}; diff --git a/docs/spec/proxy/friend_invoke.md b/docs/spec/proxy/friend_invoke.md index 2e25c14..be6fd29 100644 --- a/docs/spec/proxy/friend_invoke.md +++ b/docs/spec/proxy/friend_invoke.md @@ -45,8 +45,8 @@ PRO_DEF_MEM_DISPATCH(MemUseCount, use_count); // A direct convention operates on the contained pointer itself. struct SharedAware - : pro::facade_builder // - ::add_direct_convention // + : pro::facade_builder // + ::add_direct_convention // ::build {}; int main() { diff --git a/docs/spec/proxy/friend_reinterpret_invoke.md b/docs/spec/proxy/friend_reinterpret_invoke.md index 9278364..ee98869 100644 --- a/docs/spec/proxy/friend_reinterpret_invoke.md +++ b/docs/spec/proxy/friend_reinterpret_invoke.md @@ -36,8 +36,8 @@ For ordinary use, prefer an [`accessor`](../ProAccessible.md) or [`invoke`](frie PRO_DEF_MEM_DISPATCH(MemUseCount, use_count); struct SharedAware - : pro::facade_builder // - ::add_direct_convention // + : pro::facade_builder // + ::add_direct_convention // ::build {}; int main() { diff --git a/docs/spec/proxy_indirect_accessor/friend_reflect.md b/docs/spec/proxy_indirect_accessor/friend_reflect.md index 474df8a..bb16387 100644 --- a/docs/spec/proxy_indirect_accessor/friend_reflect.md +++ b/docs/spec/proxy_indirect_accessor/friend_reflect.md @@ -52,8 +52,8 @@ public: std::size_t Size, Align; }; -struct LayoutAware : pro::facade_builder // - ::add_indirect_reflection // +struct LayoutAware : pro::facade_builder // + ::add_indirect_reflection // ::build {}; int main() {