From 132f8d527421b57c398ee302b774fb1638cf3e45 Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Sun, 20 Sep 2026 11:24:13 +0800 Subject: [PATCH 1/3] Rename the metadata files ahead of the metadata policy Pure moves with no change in content, so that history follows each file across the rename. The next commit updates every reference to them, so this commit neither builds nor passes `mkdocs build --strict` on its own. - `facade_meta_traits.h` becomes `metadata_policy.h`. - `ProBasicMeta.md` becomes `ProBasicMetadata.md`. - `ProMeta.md` becomes `ProMetadata.md`. - `facade_aware_overload_t.md` becomes `proxy_dependent_signature.md`. --- docs/spec/{ProBasicMeta.md => ProBasicMetadata.md} | 0 docs/spec/{ProMeta.md => ProMetadata.md} | 0 .../{facade_aware_overload_t.md => proxy_dependent_signature.md} | 0 .../proxy/v5/detail/{facade_meta_traits.h => metadata_policy.h} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename docs/spec/{ProBasicMeta.md => ProBasicMetadata.md} (100%) rename docs/spec/{ProMeta.md => ProMetadata.md} (100%) rename docs/spec/{facade_aware_overload_t.md => proxy_dependent_signature.md} (100%) rename include/proxy/v5/detail/{facade_meta_traits.h => metadata_policy.h} (100%) diff --git a/docs/spec/ProBasicMeta.md b/docs/spec/ProBasicMetadata.md similarity index 100% rename from docs/spec/ProBasicMeta.md rename to docs/spec/ProBasicMetadata.md diff --git a/docs/spec/ProMeta.md b/docs/spec/ProMetadata.md similarity index 100% rename from docs/spec/ProMeta.md rename to docs/spec/ProMetadata.md diff --git a/docs/spec/facade_aware_overload_t.md b/docs/spec/proxy_dependent_signature.md similarity index 100% rename from docs/spec/facade_aware_overload_t.md rename to docs/spec/proxy_dependent_signature.md diff --git a/include/proxy/v5/detail/facade_meta_traits.h b/include/proxy/v5/detail/metadata_policy.h similarity index 100% rename from include/proxy/v5/detail/facade_meta_traits.h rename to include/proxy/v5/detail/metadata_policy.h From 2d6806706bcff13f8e6718511f0de2eef612f066 Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Sun, 20 Sep 2026 11:26:30 +0800 Subject: [PATCH 2/3] Add a metadata policy to proxy Give `proxy` a second template parameter `MetadataPolicy` that decides how an invocation is erased and how the metadata deduced from the contained type is kept. `compact_metadata`, the default, keeps small metadata in the proxy and otherwise points at a static metadata object, while `inline_metadata` always keeps the metadata in the proxy, trading size for one fewer indirection per invocation. The latter is aimed at latency-sensitive code, where the static metadata object of a long-lived proxy costs a cache line the caller would not otherwise touch. The metadata type of a `proxy` depends on both `F` and `MP`, so a proxy converts only to a proxy with the same metadata policy. The policy is chosen where the proxy type is named, and every conversion to a super preserves it. - `proxy_dependent_signature` instantiates its template argument with a facade and a metadata policy, so a convention can return a proxy that keeps the metadata policy of the proxy it was obtained from. `skills::as_view`, `skills::as_weak` and `weak_proxy::lock` do exactly that. - The policy is threaded through `proxy`, `proxy_indirect_accessor`, `proxiable`, `inplace_proxiable_target`, `proxiable_target`, `proxy_view`, `weak_proxy` and every function template that creates a proxy. The overloads that deduce the target type keep their existing signatures and always use the default policy, so naming a target type can never be mistaken for naming a policy. - Add the *ProMetadataPolicy* named requirement. A policy is not constrained by a concept, and one whose invoker or storage is not well-formed is diagnosed by `static_assert` where the proxy naming it is instantiated. Renames that prepare the vocabulary: - `compact_facade_meta_traits`/`flat_facade_meta_traits` become `compact_metadata`/`inline_metadata`. - `inplace_meta_storage` becomes `inline_meta_storage`, matching the policy that selects it. - `facade_aware_overload_t` becomes `proxy_dependent_signature`, and the conventions and signature templates that go with it drop the `faw` and `overload` spellings. - `facade_traits` becomes `proxy_traits`, because it now depends on the metadata policy as well as the facade. - *ProBasicMeta* and *ProMeta* become *ProBasicMetadata* and *ProMetadata*. nullable required a meta to name reset() and has_value(), and both restate an operation the meta already has. has_value() is the contextual conversion to bool, and reset() is assignment from a value-initialized meta, which basic_meta already requires to be well formed and nothrow. The concept becomes basic_meta plus bool-testability, and the named members are gone from sentinel_meta, invoker_base, static_meta_storage and proxy_meta_base_impl. code_ptr and meta_ptr follow, trading operator==(std::nullptr_t) and operator=(std::nullptr_t) for an explicit operator bool, so the signed wrapper and the plain pointer alias are spelled the same way. Stating the null state as a value-initialized meta moves it to the type that knows it. composite_meta holds the metas as bases, so it owns which one carries the null state: it value-initializes that first base and leaves the rest uninitialized, tests it, and copies the rest only when it holds a value. Its copy constructor delegates to the default constructor, because GCC's -Wextra flags a copy constructor that does not explicitly initialize a base with a user-provided constructor. proxy_meta_base_impl keeps only the conversion to a contained meta, and no longer distinguishes the first meta from the rest. Under pointer authentication a null value is stored unsigned, so copying one must not authenticate it. code_ptr and meta_ptr now skip the resign for a null value, in an initialize member that writes the destination from the source as proxy::initialize does. This also repairs swapping an empty proxy with a non-empty one, which exchanges the metadata words directly under trivial relocation and trapped on the null one. --- docs/spec/.pages | 8 +- docs/spec/ProBasicMetadata.md | 9 +- docs/spec/ProBasicReflection.md | 4 +- docs/spec/ProConvention.md | 4 +- docs/spec/ProFacade.md | 8 +- docs/spec/ProMetadata.md | 7 +- docs/spec/ProMetadataPolicy.md | 43 ++ docs/spec/ProOverload.md | 9 +- docs/spec/ProReflection.md | 4 +- docs/spec/README.md | 6 +- docs/spec/allocate_proxy.md | 18 +- docs/spec/allocate_proxy_shared.md | 18 +- docs/spec/basic_facade_builder/add_facade.md | 2 +- docs/spec/compact_metadata.md | 61 ++ docs/spec/inplace_proxiable_target.md | 4 +- docs/spec/make_proxy.md | 30 +- docs/spec/make_proxy_inplace.md | 18 +- docs/spec/make_proxy_shared.md | 18 +- docs/spec/make_proxy_view.md | 8 +- docs/spec/proxiable.md | 6 +- docs/spec/proxiable_target.md | 5 +- docs/spec/proxy/README.md | 19 +- docs/spec/proxy/assignment.md | 6 +- docs/spec/proxy/constructor.md | 17 +- docs/spec/proxy/destructor.md | 2 +- docs/spec/proxy/emplace.md | 2 +- docs/spec/proxy/friend_invoke.md | 18 +- docs/spec/proxy/friend_operator_equality.md | 4 +- docs/spec/proxy/friend_reflect.md | 10 +- docs/spec/proxy/friend_swap.md | 4 +- docs/spec/proxy/indirection.md | 16 +- docs/spec/proxy_dependent_signature.md | 34 +- docs/spec/proxy_indirect_accessor/README.md | 8 +- .../proxy_indirect_accessor/friend_invoke.md | 20 +- .../proxy_indirect_accessor/friend_reflect.md | 10 +- docs/spec/proxy_invoke.md | 34 +- docs/spec/proxy_reflect.md | 8 +- docs/spec/proxy_view.md | 6 +- docs/spec/skills_as_view.md | 8 +- docs/spec/skills_as_weak.md | 6 +- docs/spec/weak_proxy.md | 8 +- include/proxy/v5/detail/core.h | 567 +++++++++--------- include/proxy/v5/detail/metadata_policy.h | 72 +-- include/proxy/v5/detail/proxy_creation.h | 193 +++--- include/proxy/v5/detail/skills.h | 56 +- include/proxy/v5/proxy.ixx | 4 +- tests/BUILD.bazel | 1 + tests/CMakeLists.txt | 1 + tests/meson.build | 1 + tests/proxy_detail_tests.cpp | 73 ++- tests/proxy_invocation_tests.cpp | 30 +- tests/proxy_lifetime_tests.cpp | 16 +- tests/proxy_metadata_policy_tests.cpp | 182 ++++++ tests/proxy_pac_tests.cpp | 9 +- tests/proxy_regression_tests.cpp | 7 +- tests/proxy_traits_tests.cpp | 13 +- tests/proxy_view_tests.cpp | 12 +- 57 files changed, 1109 insertions(+), 658 deletions(-) create mode 100644 docs/spec/ProMetadataPolicy.md create mode 100644 docs/spec/compact_metadata.md create mode 100644 tests/proxy_metadata_policy_tests.cpp diff --git a/docs/spec/.pages b/docs/spec/.pages index fb90bf32..6c5f5f2f 100644 --- a/docs/spec/.pages +++ b/docs/spec/.pages @@ -8,13 +8,14 @@ nav: - Classes: - bad_proxy_cast: bad_proxy_cast.md - basic_facade_builder
facade_builder: basic_facade_builder + - compact_metadata
inline_metadata: compact_metadata.md - constraint_level: constraint_level.md - explicit_conversion_dispatch
conversion_dispatch: explicit_conversion_dispatch - - facade_aware_overload_t: facade_aware_overload_t.md - implicit_conversion_dispatch: implicit_conversion_dispatch - is_bitwise_trivially_relocatable: is_bitwise_trivially_relocatable.md - not_implemented: not_implemented.md - operator_dispatch: operator_dispatch + - proxy_dependent_signature: proxy_dependent_signature.md - proxy_indirect_accessor: proxy_indirect_accessor - proxy_view
observer_facade: proxy_view.md - proxy: proxy @@ -45,11 +46,12 @@ nav: - ProAccessible: ProAccessible.md - ProBasicConvention: ProBasicConvention.md - ProBasicFacade: ProBasicFacade.md - - ProBasicMeta: ProBasicMeta.md + - ProBasicMetadata: ProBasicMetadata.md - ProBasicReflection: ProBasicReflection.md - ProConvention: ProConvention.md - ProDispatch: ProDispatch.md - ProFacade: ProFacade.md - - ProMeta: ProMeta.md + - ProMetadata: ProMetadata.md + - ProMetadataPolicy: ProMetadataPolicy.md - ProOverload: ProOverload.md - ProReflection: ProReflection.md diff --git a/docs/spec/ProBasicMetadata.md b/docs/spec/ProBasicMetadata.md index 44199cee..0b0a3621 100644 --- a/docs/spec/ProBasicMetadata.md +++ b/docs/spec/ProBasicMetadata.md @@ -1,8 +1,8 @@ -# Named requirements: *ProBasicMeta* +# Named requirements: *ProBasicMetadata* > Since: 5.0.0 -A type `M` meets the *ProBasicMeta* requirements if the following expressions are well-formed and have the specified semantics (let `m` be a value of type `M`, `cm` be a value of type `const M`). +A type `M` meets the *ProBasicMetadata* requirements if `M` is a class type, and the following expressions are well-formed and have the specified semantics (let `m` be a value of type `M`, `cm` be a value of type `const M`). | Expressions | Semantics | | ----------- | ------------------------------------------------------------ | @@ -13,9 +13,10 @@ A type `M` meets the *ProBasicMeta* requirements if the following expressions ar ## Notes -A "meta" is an object holding metadata deduced from a type at compile time, stored in or referenced by a [`proxy`](proxy/README.md). Because `proxy` creates, copies, assigns, and destroys metadata in contexts specified not to throw, none of these operations may throw. +"Metadata" is an object holding information deduced from a type at compile time, stored in or referenced by a [`proxy`](proxy/README.md). Because `proxy` creates, copies, assigns, and destroys metadata in contexts specified not to throw, none of these operations may throw. ## See Also - [*ProBasicReflection* requirements](ProBasicReflection.md) -- [*ProMeta* requirements](ProMeta.md) +- [*ProMetadata* requirements](ProMetadata.md) +- [*ProMetadataPolicy* requirements](ProMetadataPolicy.md) diff --git a/docs/spec/ProBasicReflection.md b/docs/spec/ProBasicReflection.md index e845dfd3..293c0fa7 100644 --- a/docs/spec/ProBasicReflection.md +++ b/docs/spec/ProBasicReflection.md @@ -7,10 +7,10 @@ A type `R` meets the *ProBasicReflection* requirements if the following expressi | Expressions | Semantics | | ---------------------------- | ------------------------------------------------------------ | | `R::is_direct` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `bool`, specifying whether the reflection applies to a pointer type itself (`true`), or the element type of a pointer type (`false`). | -| `typename R::reflector_type` | A type that defines the data structure reflected from the type. Shall meet the [*ProBasicMeta* requirements](ProBasicMeta.md) *(since 5.0.0)*. | +| `typename R::reflector_type` | A type that defines the data structure reflected from the type. Shall meet the [*ProBasicMetadata* requirements](ProBasicMetadata.md) *(since 5.0.0)*. | ## See Also - [*ProBasicFacade* requirements](ProBasicFacade.md) -- [*ProBasicMeta* requirements](ProBasicMeta.md) +- [*ProBasicMetadata* requirements](ProBasicMetadata.md) - [*ProReflection* requirements](ProReflection.md) diff --git a/docs/spec/ProConvention.md b/docs/spec/ProConvention.md index 2d2ac7c3..1bf6c326 100644 --- a/docs/spec/ProConvention.md +++ b/docs/spec/ProConvention.md @@ -1,10 +1,10 @@ # Named requirements: *ProConvention* -A type `C` meets the *ProConvention* requirements of a type `P` if `C` meets the [*ProBasicConvention* requirements](ProBasicConvention.md), and the following expressions are well-formed and have the specified semantics. +A type `C` meets the *ProConvention* requirements of a type `P` and a type `MP`, where `MP` meets the [*ProMetadataPolicy* requirements](ProMetadataPolicy.md), if `C` meets the [*ProBasicConvention* requirements](ProBasicConvention.md), and the following expressions are well-formed and have the specified semantics. | Expressions | Semantics | | ---------------------------- | ------------------------------------------------------------ | -| `typename C::overload_type` | A type `O` that meets the [*ProOverload* requirements](ProOverload.md), where
- when `C::is_direct` is `true`, `typename C::dispatch_type` shall meet the [*ProDispatch* requirements](ProDispatch.md) of `P` and `O`,
- or otherwise, when `C::is_direct` is `false`, let `QP` be a qualified reference type of `P` with the *cv ref* qualifiers defined by `O` (`QP` is an lvalue reference type if `O` does not define a *ref* qualifier), `qp` be a value of `QP`, `*std::forward(qp)` shall be well-formed, and `typename C::dispatch_type` shall meet the [*ProDispatch* requirements](ProDispatch.md) of `decltype(*std::forward(qp))` and `O`. | +| `typename C::overload_type` | A type `O` such that [`substituted-overload`](ProOverload.md)`` meets the [*ProOverload* requirements](ProOverload.md) for the facade type `F` that declares `C`, where
- when `C::is_direct` is `true`, `typename C::dispatch_type` shall meet the [*ProDispatch* requirements](ProDispatch.md) of `P` and `O`,
- or otherwise, when `C::is_direct` is `false`, let `QP` be a qualified reference type of `P` with the *cv ref* qualifiers defined by `O` (`QP` is an lvalue reference type if `O` does not define a *ref* qualifier), `qp` be a value of `QP`, `*std::forward(qp)` shall be well-formed, and `typename C::dispatch_type` shall meet the [*ProDispatch* requirements](ProDispatch.md) of `decltype(*std::forward(qp))` and `O`. | ## See Also diff --git a/docs/spec/ProFacade.md b/docs/spec/ProFacade.md index 22da818c..36464e38 100644 --- a/docs/spec/ProFacade.md +++ b/docs/spec/ProFacade.md @@ -1,11 +1,11 @@ # Named requirements: *ProFacade* -A type `F` meets the *ProFacade* requirements of a type `P` if `F` meets the [*ProBasicFacade* requirements](ProBasicFacade.md), and the following expressions are well-formed and have the specified semantics. +A type `F` meets the *ProFacade* requirements of a type `P` and a type `MP`, where `MP` meets the [*ProMetadataPolicy* requirements](ProMetadataPolicy.md), if `F` meets the [*ProBasicFacade* requirements](ProBasicFacade.md), and the following expressions are well-formed and have the specified semantics. | Expressions | Semantics | | ---------------------------------------------- | ------------------------------------------------------------ | -| `typename F::super_types`
*(since 5.0.0)* | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of types `Ss`. Each type `S` in `Ss` shall meet the *ProFacade* requirements of `P`. | -| `typename F::convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of types `Cs`. Each type `C` in `Cs` shall meet the [*ProConvention* requirements](ProConvention.md) of `P`. | +| `typename F::super_types`
*(since 5.0.0)* | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of types `Ss`. Each type `S` in `Ss` shall meet the *ProFacade* requirements of `P` and `MP`. | +| `typename F::convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of types `Cs`. Each type `C` in `Cs` shall meet the [*ProConvention* requirements](ProConvention.md) of `P` and `MP`. | | `typename F::reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of types `Rs`. Each type `R` in `Rs` shall meet the [*ProReflection* requirements](ProReflection.md) of `P`. | | `F::max_size` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `std::size_t` that shall be greater than or equal to `sizeof(P)`. | | `F::max_align` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `std::size_t` that shall be greater than or equal to `alignof(P)`. | @@ -13,7 +13,7 @@ A type `F` meets the *ProFacade* requirements of a type `P` if `F` meets the [*P | `F::relocatability` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type [`constraint_level`](constraint_level.md) that defines the required relocatability of `P`. | | `F::destructibility` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type [`constraint_level`](constraint_level.md) that defines the required destructibility of `P`. | -*Since 5.0.0*: let `Cs` be the conventions of `F` and of every super of `F`, reachable via `typename F::super_types` transitively. Each type `C` in `Cs` whose `typename C::overload_type` is a specialization of [`facade_aware_overload_t`](facade_aware_overload_t.md) shall also meet the [*ProConvention* requirements](ProConvention.md) of `P` with [`substituted-overload`](ProOverload.md)`` in place of `typename C::overload_type`. Among the types in `Cs` sharing `is_direct` and `dispatch_type`, distinct `overload_type`s shall substitute to distinct overloads. +*Since 5.0.0*: let `Cs` be the conventions of `F` and of every super of `F`, reachable via `typename F::super_types` transitively. Each type `C` in `Cs` whose `typename C::overload_type` is a specialization of [`proxy_dependent_signature`](proxy_dependent_signature.md) shall also meet the [*ProConvention* requirements](ProConvention.md) of `P` with [`substituted-overload`](ProOverload.md)`` in place of `typename C::overload_type`. Among the types in `Cs` sharing `is_direct` and `dispatch_type`, distinct `overload_type`s shall substitute to distinct overloads. *Since 4.0.2*: `P` shall be a pointer-like type eligible for `proxy`. A type `P` is eligible if the following condition is satisfied: diff --git a/docs/spec/ProMetadata.md b/docs/spec/ProMetadata.md index 30dbccfd..6d16b604 100644 --- a/docs/spec/ProMetadata.md +++ b/docs/spec/ProMetadata.md @@ -1,8 +1,8 @@ -# Named requirements: *ProMeta* +# Named requirements: *ProMetadata* > Since: 5.0.0 -A type `M` meets the *ProMeta* requirements of a type `T` if `M` meets the [*ProBasicMeta* requirements](ProBasicMeta.md), and the following expressions are well-formed and have the specified semantics. +A type `M` meets the *ProMetadata* requirements of a type `T` if `M` meets the [*ProBasicMetadata* requirements](ProBasicMetadata.md), and the following expressions are well-formed and have the specified semantics. | Expressions | Semantics | | -------------------------- | ------------------------------------------------------------ | @@ -10,5 +10,6 @@ A type `M` meets the *ProMeta* requirements of a type `T` if `M` meets the [*Pro ## See Also -- [*ProBasicMeta* requirements](ProBasicMeta.md) +- [*ProBasicMetadata* requirements](ProBasicMetadata.md) +- [*ProMetadataPolicy* requirements](ProMetadataPolicy.md) - [*ProReflection* requirements](ProReflection.md) diff --git a/docs/spec/ProMetadataPolicy.md b/docs/spec/ProMetadataPolicy.md new file mode 100644 index 00000000..4d26f429 --- /dev/null +++ b/docs/spec/ProMetadataPolicy.md @@ -0,0 +1,43 @@ +# Named requirements: *ProMetadataPolicy* + +> Since: 5.0.0 + +A metadata policy determines how a [`proxy`](proxy/README.md) erases an invocation and how it keeps the metadata deduced from the contained type. + +A nullable type is a type meeting the [*ProBasicMetadata* requirements](ProBasicMetadata.md) whose default-constructed value holds nothing, and for which `static_cast(v)` is a non-throwing expression that yields `false` if and only if `v` holds nothing. + +A type `MP` meets the *ProMetadataPolicy* requirements if the following expressions are well-formed and have the specified semantics, where + +- `Ctx` is an implementation-defined *erased context* type that identifies the contained value of a `proxy`, and for which an implementation-defined function template `invoke` is found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl), +- `O` is a type meeting the [*ProOverload* requirements](ProOverload.md), `R` is the return type of `O` and `Args...` are the argument types of `O`, +- `P` is a pointer type eligible for `proxy` (see [*ProFacade* requirements](ProFacade.md)), +- `M` is a nullable type meeting the [*ProBasicMetadata* requirements](ProBasicMetadata.md) and the [*ProMetadata* requirements](ProMetadata.md) of `P`. + +| Expressions | Semantics | +| --------------------------------------- | ------------------------------------------------------------ | +| `typename MP::template invoker` | A nullable type `I` meeting the [*ProBasicMetadata* requirements](ProBasicMetadata.md). `I` shall not be [final](https://en.cppreference.com/w/cpp/language/final). | +| `typename MP::template storage` | A nullable type `S` meeting the [*ProBasicMetadata* requirements](ProBasicMetadata.md). | + +Let `ci` be a value of type `const I`, `ctx` be a value of type `Ctx`, `args...` be values of type `Args...`, `s` be a value of type `S`, and `cs` be a value of type `const S`. The following expressions shall be well-formed and have the specified semantics. + +| Expressions | Semantics | +| -------------------------------------- | ------------------------------------------------------------ | +| `I(std::in_place_type

)` | Creates an object of type `I` that holds an invoker of `P`, shall not throw. | +| `ci(ctx, std::forward(args)...)` | Has the same effect as `invoke

(ctx, std::forward(args)...)`, where `P` is the type `ci` was created with, and the return type is `R`. Shall not throw when `O` is a `noexcept` overload. The behavior is undefined when `ci` holds no invoker. | +| `S(std::in_place_type

)` | Creates an object of type `S` that holds the metadata `M(std::in_place_type

)`, shall not throw. | +| `*cs` | A `const M&` referring to the metadata held by `cs`. The behavior is undefined when `cs` holds no metadata. | +| `s = cs2` | Where `cs2` is a value of type `const MP::template storage`, for some type `M2` whose `const M2&` is [nothrow-convertible](https://en.cppreference.com/w/cpp/types/is_convertible) to `const M&`. Replaces the metadata of `s` with the metadata of `cs2` converted to `M`, shall not throw. The behavior is undefined when `cs2` holds no metadata. | + +## Notes + +`I` is required not to be final because `proxy` composes the invokers of all the conventions of a facade into a single metadata object by inheritance. + +The last expression is what makes a conversion to a super well-formed. The metadata of a super is reachable from the metadata of the deriving facade, so assigning the latter to the former transfers the invokers the super needs. + +The metadata type of a [`proxy`](proxy/README.md)`` depends on both `F` and `MP`, so a `proxy` converts only to a `proxy` with the same metadata policy. The metadata policy is therefore chosen once, where the `proxy` type is named, and every conversion from that point on stays within it. + +## See Also + +- [class `compact_metadata`
class `inline_metadata`](compact_metadata.md) +- [*ProBasicMetadata* requirements](ProBasicMetadata.md) +- [*ProMetadata* requirements](ProMetadata.md) diff --git a/docs/spec/ProOverload.md b/docs/spec/ProOverload.md index 3f02d53d..40010bcd 100644 --- a/docs/spec/ProOverload.md +++ b/docs/spec/ProOverload.md @@ -1,11 +1,11 @@ # Named requirements: *ProOverload* -A type `O` meets the *ProOverload* requirements if `substituted-overload` matches one of the following definitions, where `F` is any type meeting the [*ProBasicFacade* requirements](ProBasicFacade.md), `R` is the *return type*, `Args...` are the *argument types*. +A type `O` meets the *ProOverload* requirements if `substituted-overload` matches one of the following definitions, where `F` is any type meeting the [*ProBasicFacade* requirements](ProBasicFacade.md), `MP` is any type meeting the [*ProMetadataPolicy* requirements](ProMetadataPolicy.md), `R` is the *return type*, `Args...` are the *argument types*. -The exposition-only type `substituted-overload` is `OT` if `O` is a specialization of [`facade_aware_overload_t`](facade_aware_overload_t.md), or `O` otherwise. +*Since 5.0.0*: the exposition-only type `substituted-overload` is `OT` if `O` is a specialization of [`proxy_dependent_signature`](proxy_dependent_signature.md), or `O` otherwise. Previously the exposition-only type was `substituted-overload`, and `OT` was instantiated with `F` only. -| Definitions of `substituted-overload` | -| ------------------------------------------- | +| Definitions of `substituted-overload` | +| ----------------------------------------------- | | `R(Args...)` | | `R(Args...) noexcept` | | `R(Args...) &` | @@ -22,4 +22,5 @@ The exposition-only type `substituted-overload` is `OT` if `O` is a spe ## See Also - [*ProConvention* requirements](ProConvention.md) +- [*ProMetadataPolicy* requirements](ProMetadataPolicy.md) - [class template `std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function) diff --git a/docs/spec/ProReflection.md b/docs/spec/ProReflection.md index 78781441..9fbdc9fd 100644 --- a/docs/spec/ProReflection.md +++ b/docs/spec/ProReflection.md @@ -6,9 +6,9 @@ A type `R` meets the *ProReflection* requirements of a type `P` if `R` meets the | Expressions | Semantics | | --------------------------------------------------- | ------------------------------------------------------------ | -| `typename R::reflector_type(std::in_place_type)` | Constructs a value of type `typename R::reflector_type`, reflecting implementation-defined metadata of type `T`. `typename R::reflector_type` shall meet the [*ProMeta* requirements](ProMeta.md) of `T` *(since 5.0.0)*. | +| `typename R::reflector_type(std::in_place_type)` | Constructs a value of type `typename R::reflector_type`, reflecting implementation-defined metadata of type `T`. `typename R::reflector_type` shall meet the [*ProMetadata* requirements](ProMetadata.md) of `T` *(since 5.0.0)*. | ## See Also - [*ProFacade* requirements](ProFacade.md) -- [*ProMeta* requirements](ProMeta.md) +- [*ProMetadata* requirements](ProMetadata.md) diff --git a/docs/spec/README.md b/docs/spec/README.md index 4254cd10..390d2019 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -21,13 +21,14 @@ This document provides the API specifications for the C++ library Proxy (version | ------------------------------------------------------------ | ------------------------------------------------------------ | | [`bad_proxy_cast`](bad_proxy_cast.md) | Exception thrown by the value-returning forms of `proxy_cast` on a type mismatch | | [`basic_facade_builder`
`facade_builder`](basic_facade_builder/README.md) | Provides capability to build a facade type at compile-time | +| [`compact_metadata`
`inline_metadata`](compact_metadata.md) | The metadata policies provided by the library | | [`constraint_level`](constraint_level.md) | Defines the 4 constraint levels of a special member function | | [`explicit_conversion_dispatch`
`conversion_dispatch`](explicit_conversion_dispatch/README.md) | Dispatch type for explicit conversion expressions with accessibility | -| [`facade_aware_overload_t`](facade_aware_overload_t.md) | Specifies a facade-aware overload template | | [`implicit_conversion_dispatch`](implicit_conversion_dispatch/README.md) | Dispatch type for implicit conversion expressions with accessibility | | [`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_dependent_signature`](proxy_dependent_signature.md) | Specifies a proxy-dependent signature template | | [`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 | @@ -85,9 +86,12 @@ Also included in `proxy.h`. | [*ProAccessible*](ProAccessible.md) | Specifies that a type provides accessibility to `proxy` | | [*ProBasicConvention*](ProBasicConvention.md) | Specifies that a type potentially models a "convention" | | [*ProBasicFacade*](ProBasicFacade.md) | Specifies that a type potentially models a "facade" of `proxy` | +| [*ProBasicMetadata*](ProBasicMetadata.md) | Specifies that a type potentially models "metadata" | | [*ProBasicReflection*](ProBasicReflection.md) | Specifies that a type potentially models a "reflection" | | [*ProConvention*](ProConvention.md) | Specifies that a type models a "convention" | | [*ProDispatch*](ProDispatch.md) | Specifies that a type models a "dispatch" | | [*ProFacade*](ProFacade.md) | Specifies that a type models a "facade" of `proxy` | +| [*ProMetadata*](ProMetadata.md) | Specifies that a type models "metadata" of a type | +| [*ProMetadataPolicy*](ProMetadataPolicy.md) | Specifies that a type models a "metadata policy" of `proxy` | | [*ProOverload*](ProOverload.md) | Specifies that a type models an "overload" | | [*ProReflection*](ProReflection.md) | Specifies that a type models a "reflection" | diff --git a/docs/spec/allocate_proxy.md b/docs/spec/allocate_proxy.md index c2436a10..e0b75c96 100644 --- a/docs/spec/allocate_proxy.md +++ b/docs/spec/allocate_proxy.md @@ -12,21 +12,25 @@ template proxy allocate_proxy(const Alloc& alloc, T&& value); // freestanding-deleted // (2) -template -proxy allocate_proxy(const Alloc& alloc, Args&&... args); // freestanding-deleted +template +proxy allocate_proxy(const Alloc& alloc, Args&&... args); // freestanding-deleted // (3) -template -proxy allocate_proxy(const Alloc& alloc, std::initializer_list il, Args&&... args); // freestanding-deleted +template +proxy allocate_proxy(const Alloc& alloc, std::initializer_list il, Args&&... args); // freestanding-deleted ``` +Let `MP` be the [metadata policy](ProMetadataPolicy.md) of the created `proxy`, which is [`compact_metadata`](compact_metadata.md) for `(1)`. + `(1)` Creates a `proxy` object containing a value `p` of type *allocated-ptr<*`std::decay_t`*, Alloc>*, where `*p` is direct-non-list-initialized with `std::forward(value)`. -`(2)` Creates a `proxy` object containing a value `p` of type *allocated-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `std::forward(args)...`. +`(2)` Creates a `proxy` object containing a value `p` of type *allocated-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `std::forward(args)...`. + +`(3)` Creates a `proxy` object containing a value `p` of type *allocated-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `il, std::forward(args)...`. -`(3)` Creates a `proxy` object containing a value `p` of type *allocated-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `il, std::forward(args)...`. +*Since 3.3.0*: For `(1-3)`, if [`proxiable_target, F, MP>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. -*Since 3.3.0*: For `(1-3)`, if [`proxiable_target, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. +*Since 5.0.0*: `(2-3)` can name the metadata policy of the created `proxy`. `(1)` deduces the target type, so it always uses the default policy, and a `proxy` with another policy is created by naming the target type as well. ## Return Value diff --git a/docs/spec/allocate_proxy_shared.md b/docs/spec/allocate_proxy_shared.md index 84b90ddb..b40aed82 100644 --- a/docs/spec/allocate_proxy_shared.md +++ b/docs/spec/allocate_proxy_shared.md @@ -13,21 +13,25 @@ template proxy allocate_proxy_shared(const Alloc& alloc, T&& value); // freestanding-deleted // (2) -template -proxy allocate_proxy_shared(const Alloc& alloc, Args&&... args); // freestanding-deleted +template +proxy allocate_proxy_shared(const Alloc& alloc, Args&&... args); // freestanding-deleted // (3) -template -proxy allocate_proxy_shared(const Alloc& alloc, std::initializer_list il, Args&&... args); // freestanding-deleted +template +proxy allocate_proxy_shared(const Alloc& alloc, std::initializer_list il, Args&&... args); // freestanding-deleted ``` +Let `MP` be the [metadata policy](ProMetadataPolicy.md) of the created `proxy`, which is [`compact_metadata`](compact_metadata.md) for `(1)`. + `(1)` Creates a `proxy` object containing a value `p` of type *strong-compact-ptr<*`std::decay_t`*, Alloc>*, where `*p` is direct-non-list-initialized with `std::forward(value)`. -`(2)` Creates a `proxy` object containing a value `p` of type *strong-compact-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `std::forward(args)...`. +`(2)` Creates a `proxy` object containing a value `p` of type *strong-compact-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `std::forward(args)...`. + +`(3)` Creates a `proxy` object containing a value `p` of type *strong-compact-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `il, std::forward(args)...`. -`(3)` Creates a `proxy` object containing a value `p` of type *strong-compact-ptr<T, Alloc>*, where `*p` is direct-non-list-initialized with `il, std::forward(args)...`. +For `(1-3)`, if [`proxiable_target, F, MP>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. -For `(1-3)`, if [`proxiable_target, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. +*Since 5.0.0*: `(2-3)` can name the metadata policy of the created `proxy`. `(1)` deduces the target type, so it always uses the default policy, and a `proxy` with another policy is created by naming the target type as well. ## Return Value diff --git a/docs/spec/basic_facade_builder/add_facade.md b/docs/spec/basic_facade_builder/add_facade.md index 2a5eb076..eb77e871 100644 --- a/docs/spec/basic_facade_builder/add_facade.md +++ b/docs/spec/basic_facade_builder/add_facade.md @@ -20,7 +20,7 @@ The alias template `add_facade` of `basic_facade_builder` needs no indirect call to translate the metadata. The contained value is still copied or relocated as it would be by a copy or a move of a `proxy` of the built facade, which involves an indirect call unless the corresponding [`constraint_level`](../constraint_level.md) is `trivial`. Two consequences of embedding are worth noting. When a super is reachable through more than one other super (a diamond), its metadata is embedded once per path. When the built facade strengthens a [`constraint_level`](../constraint_level.md) that `F` also declares (for example from `nontrivial` to `nothrow`), both levels are represented. Either case makes the metadata larger than the sum of the distinct conventions, and nesting diamonds compounds the effect. Metadata of that size is held out of line and shared by every `proxy` of the facade, so the cost is in static data rather than in `sizeof(proxy)`. diff --git a/docs/spec/compact_metadata.md b/docs/spec/compact_metadata.md new file mode 100644 index 00000000..3d6fd692 --- /dev/null +++ b/docs/spec/compact_metadata.md @@ -0,0 +1,61 @@ +# Class `compact_metadata`
Class `inline_metadata` + +> Header: `proxy.h` +> Module: `proxy` +> Namespace: `pro::inline v5` +> Since: 5.0.0 + +```cpp +struct compact_metadata; +struct inline_metadata; +``` + +`compact_metadata` and `inline_metadata` are the metadata policies provided by the library. Both meet the [*ProMetadataPolicy* requirements](ProMetadataPolicy.md) and erase an invocation the same way. They differ only in how a [`proxy`](proxy/README.md) keeps the metadata deduced from the contained type. + +| Name | Metadata storage | +| ------------------ | ------------------------------------------------------------ | +| `compact_metadata` | The metadata is kept in the `proxy` object when it is no larger than a pointer, and otherwise the `proxy` keeps a pointer to a static metadata object of the contained type. | +| `inline_metadata` | The metadata is always kept in the `proxy` object. | + +`compact_metadata` is the default metadata policy of `proxy` and of every function template that creates a `proxy`. + +A `proxy` converts only to a `proxy` with the same metadata policy, so the policy is chosen where the `proxy` type is named and is preserved by every conversion to a super, by [`skills::as_view`](skills_as_view.md), by [`skills::as_weak`](skills_as_weak.md) and by [`weak_proxy::lock`](weak_proxy.md). + +## Notes + +`inline_metadata` trades size for one fewer indirection on every invocation. A `proxy` with `inline_metadata` is as large as its pointer storage plus its whole metadata, while an invocation reads the invoker directly from the `proxy` instead of following a pointer to a static metadata object. `compact_metadata` keeps `sizeof(proxy)` at the size of the pointer storage plus one pointer, at the cost of that indirection when the metadata is larger than a pointer. + +The indirection of `compact_metadata` costs more than one load when the `proxy` is long-lived and invoked from a cold path. The static metadata object lives away from the `proxy`, so reaching it touches a cache line the caller would not otherwise bring in, while inline metadata rides in the lines already fetched for the `proxy` itself. `inline_metadata` is aimed at that case, and at latency-sensitive code in general, rather than at throughput in a hot loop where the static object stays cached. + +## Example + +```cpp +#include +#include + +#include + +PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); + +struct Stringable : pro::facade_builder // + ::add_convention // + ::support_copy // + ::build {}; + +int main() { + pro::proxy p1 = pro::make_proxy(123); + pro::proxy p2 = + pro::make_proxy(123); + std::cout << ToString(*p1) << "\n"; // Prints "123" + std::cout << ToString(*p2) << "\n"; // Prints "123" + + // Keeping the metadata inline makes the proxy larger + std::cout << std::boolalpha << (sizeof(p2) > sizeof(p1)) + << "\n"; // Prints "true" +} +``` + +## See Also + +- [class template `proxy`](proxy/README.md) +- [*ProMetadataPolicy* requirements](ProMetadataPolicy.md) diff --git a/docs/spec/inplace_proxiable_target.md b/docs/spec/inplace_proxiable_target.md index c93d5fc1..40f888fd 100644 --- a/docs/spec/inplace_proxiable_target.md +++ b/docs/spec/inplace_proxiable_target.md @@ -5,8 +5,8 @@ > Namespace: `pro::inline v5` ```cpp -template -concept inplace_proxiable_target = proxiable, F>; +template +concept inplace_proxiable_target = proxiable, F, MP>; ``` See [`make_proxy_inplace`](make_proxy_inplace.md) for the definition of the exposition-only class template *inplace-ptr*. diff --git a/docs/spec/make_proxy.md b/docs/spec/make_proxy.md index 561d8e5a..680291a2 100644 --- a/docs/spec/make_proxy.md +++ b/docs/spec/make_proxy.md @@ -7,12 +7,12 @@ The definitions of `make_proxy` make use of the following exposition-only function: ```cpp -template -proxy make-proxy-internal(Args&&... args) { - if constexpr (inplace_proxiable_target) { - return make_proxy_inplace(std::forward(args)...); +template +proxy make-proxy-internal(Args&&... args) { + if constexpr (inplace_proxiable_target) { + return make_proxy_inplace(std::forward(args)...); } else { - return allocate_proxy(std::allocator{}, std::forward(args)...); + return allocate_proxy(std::allocator{}, std::forward(args)...); } } ``` @@ -23,21 +23,25 @@ template proxy make_proxy(T&& value); // freestanding-deleted // (2) -template -proxy make_proxy(Args&&... args); // freestanding-deleted +template +proxy make_proxy(Args&&... args); // freestanding-deleted // (3) -template -proxy make_proxy(std::initializer_list il, Args&&... args); // freestanding-deleted +template +proxy make_proxy(std::initializer_list il, Args&&... args); // freestanding-deleted ``` -`(1)` Equivalent to `return make-proxy-internal>(std::forward(value))`. +Let `MP` be the [metadata policy](ProMetadataPolicy.md) of the created `proxy`, which is [`compact_metadata`](compact_metadata.md) for `(1)`. -`(2)` Equivalent to `return make-proxy-internal(std::forward(args)...)`. +`(1)` Equivalent to `return make-proxy-internal>(std::forward(value))`. -`(3)` Equivalent to `return make-proxy-internal(il, std::forward(args)...)`. +`(2)` Equivalent to `return make-proxy-internal(std::forward(args)...)`. -*Since 3.3.0*: For `(1-3)`, if [`proxiable_target, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. +`(3)` Equivalent to `return make-proxy-internal(il, std::forward(args)...)`. + +*Since 3.3.0*: For `(1-3)`, if [`proxiable_target, F, MP>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. + +*Since 5.0.0*: `(2-3)` can name the metadata policy of the created `proxy`. `(1)` deduces the target type, so it always uses the default policy, and a `proxy` with another policy is created by naming the target type as well. ## Return Value diff --git a/docs/spec/make_proxy_inplace.md b/docs/spec/make_proxy_inplace.md index 8fd5f3f2..eba304e4 100644 --- a/docs/spec/make_proxy_inplace.md +++ b/docs/spec/make_proxy_inplace.md @@ -14,26 +14,30 @@ proxy make_proxy_inplace(T&& value) requires(std::is_constructible_v, T>); // (2) -template -proxy make_proxy_inplace(Args&&... args) +template +proxy make_proxy_inplace(Args&&... args) noexcept(std::is_nothrow_constructible_v) requires(std::is_constructible_v); // (3) -template -proxy make_proxy_inplace(std::initializer_list il, Args&&... args) +template +proxy make_proxy_inplace(std::initializer_list il, Args&&... args) noexcept(std::is_nothrow_constructible_v< T, std::initializer_list&, Args...>) requires(std::is_constructible_v&, Args...>); ``` +Let `MP` be the [metadata policy](ProMetadataPolicy.md) of the created `proxy`, which is [`compact_metadata`](compact_metadata.md) for `(1)`. + `(1)` Creates a `proxy` object containing a value `p` of type *inplace-ptr<*`std::decay_t`*>*, where `*p` is direct-non-list-initialized with `std::forward(value)`. -`(2)` Creates a `proxy` object containing a value `p` of type *inplace-ptr<T>*, where `*p` is direct-non-list-initialized with `std::forward(args)...`. +`(2)` Creates a `proxy` object containing a value `p` of type *inplace-ptr<T>*, where `*p` is direct-non-list-initialized with `std::forward(args)...`. + +`(3)` Creates a `proxy` object containing a value `p` of type *inplace-ptr<T>*, where `*p` is direct-non-list-initialized with `il, std::forward(args)...`. -`(3)` Creates a `proxy` object containing a value `p` of type *inplace-ptr<T>*, where `*p` is direct-non-list-initialized with `il, std::forward(args)...`. +*Since 3.3.0*: For `(1-3)`, if [`inplace_proxiable_target, F, MP>`](inplace_proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. -*Since 3.3.0*: For `(1-3)`, if [`inplace_proxiable_target, F>`](inplace_proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. +*Since 5.0.0*: `(2-3)` can name the metadata policy of the created `proxy`. `(1)` deduces the target type, so it always uses the default policy, and a `proxy` with another policy is created by naming the target type as well. ## Return Value diff --git a/docs/spec/make_proxy_shared.md b/docs/spec/make_proxy_shared.md index b8c07817..776f46eb 100644 --- a/docs/spec/make_proxy_shared.md +++ b/docs/spec/make_proxy_shared.md @@ -11,21 +11,25 @@ template proxy make_proxy_shared(T&& value); // freestanding-deleted // (2) -template -proxy make_proxy_shared(Args&&... args); // freestanding-deleted +template +proxy make_proxy_shared(Args&&... args); // freestanding-deleted // (3) -template -proxy make_proxy_shared(std::initializer_list il, Args&&... args); // freestanding-deleted +template +proxy make_proxy_shared(std::initializer_list il, Args&&... args); // freestanding-deleted ``` +Let `MP` be the [metadata policy](ProMetadataPolicy.md) of the created `proxy`, which is [`compact_metadata`](compact_metadata.md) for `(1)`. + `(1)` Equivalent to `return allocate_proxy_shared>(std::allocator{}, std::forward(value))`. -`(2)` Equivalent to `return allocate_proxy_shared(std::allocator{}, std::forward(args)...)`. +`(2)` Equivalent to `return allocate_proxy_shared(std::allocator{}, std::forward(args)...)`. + +`(3)` Equivalent to `return allocate_proxy_shared(std::allocator{}, il, std::forward(args)...)`. -`(3)` Equivalent to `return allocate_proxy_shared(std::allocator{}, il, std::forward(args)...)`. +*Since 3.3.0*: For `(1-3)`, if [`proxiable_target, F, MP>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. -*Since 3.3.0*: For `(1-3)`, if [`proxiable_target, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. +*Since 5.0.0*: `(2-3)` can name the metadata policy of the created `proxy`. `(1)` deduces the target type, so it always uses the default policy, and a `proxy` with another policy is created by naming the target type as well. ## Return Value diff --git a/docs/spec/make_proxy_view.md b/docs/spec/make_proxy_view.md index 102111e8..5b6d4822 100644 --- a/docs/spec/make_proxy_view.md +++ b/docs/spec/make_proxy_view.md @@ -8,11 +8,13 @@ The definition of `make_proxy_view` makes use of an exposition-only class template *observer-ptr*. `observer-ptr` contains a raw pointer to an object of type `T`, and provides `operator*` for access with the same qualifiers. ```cpp -template -proxy_view make_proxy_view(T& value) noexcept; +template +proxy_view make_proxy_view(T& value) noexcept; ``` -Creates a `proxy_view` object containing a value `p` of type `observer-ptr`, where `p` is direct-non-list-initialized with `std::addressof(value)`. If [`proxiable_target`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. +Creates a `proxy_view` object containing a value `p` of type `observer-ptr`, where `p` is direct-non-list-initialized with `std::addressof(value)`. If [`proxiable_target`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated. + +*Since 5.0.0*: the [metadata policy](ProMetadataPolicy.md) of the created `proxy_view` can be named explicitly, and defaults to [`compact_metadata`](compact_metadata.md). `make_proxy_view` has a single overload and no target-type parameter, so the policy is named right after the facade. ## Return Value diff --git a/docs/spec/proxiable.md b/docs/spec/proxiable.md index 07bcd4cd..82c4d6a6 100644 --- a/docs/spec/proxiable.md +++ b/docs/spec/proxiable.md @@ -5,11 +5,13 @@ > Namespace: `pro::inline v5` ```cpp -template +template concept proxiable = /* see-below */; ``` -The concept `proxiable` specifies that [`proxy`](proxy/README.md) can potentially contain a value of type `P`. If `P` is an incomplete type, the behavior of evaluating `proxiable` is undefined. `proxiable` is `true` when `F` meets the [*ProFacade* requirements](ProFacade.md) of `P`; otherwise, it is `false`. +The concept `proxiable` specifies that [`proxy`](proxy/README.md) can potentially contain a value of type `P`. If `P` is an incomplete type, the behavior of evaluating `proxiable` is undefined. `proxiable` is `true` when `F` meets the [*ProFacade* requirements](ProFacade.md) of `P` and `MP`; otherwise, it is `false`. + +*Since 5.0.0*: `proxiable` takes a [metadata policy](ProMetadataPolicy.md), which participates in the check when a convention of `F` is declared with a [`proxy_dependent_signature`](proxy_dependent_signature.md). `MP` is not itself checked by `proxiable`, and a type that does not meet the *ProMetadataPolicy* requirements is diagnosed where `proxy` is instantiated. ## Example diff --git a/docs/spec/proxiable_target.md b/docs/spec/proxiable_target.md index 8582e93b..6a295d8c 100644 --- a/docs/spec/proxiable_target.md +++ b/docs/spec/proxiable_target.md @@ -6,8 +6,9 @@ > Since: 3.3.0 ```cpp -template -concept proxiable_target = proxiable, observer_facade>; +template +concept proxiable_target = + proxiable, observer_facade, MP>; ``` See [`make_proxy_view`](make_proxy_view.md) for the definition of the exposition-only class template *observer-ptr*. diff --git a/docs/spec/proxy/README.md b/docs/spec/proxy/README.md index 484b119f..dc2ed807 100644 --- a/docs/spec/proxy/README.md +++ b/docs/spec/proxy/README.md @@ -5,26 +5,29 @@ > Namespace: `pro::inline v5` ```cpp -template +template class proxy; ``` Class template `proxy` is a general-purpose polymorphic wrapper for C++ objects. Unlike other polymorphic wrappers in the C++ standard (e.g., [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function), [`std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function), [`std::any`](https://en.cppreference.com/w/cpp/utility/any), etc.), `proxy` is based on pointer semantics. It supports flexible lifetime management without runtime [garbage collection (GC)](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)), and offers best-in-class code generation quality, extendibility and accessibility. -Any instance of `proxy` at any given point in time either *contains a value* or *does not contain a value*. If a `proxy` *contains a value*, the type of the value shall be a pointer type `P` where [`proxiable`](../proxiable.md) is `true`, and the value is guaranteed to be allocated as part of the `proxy` object footprint, i.e. no dynamic memory allocation occurs. However, `P` may allocate during its construction, depending on its implementation. +The [metadata policy](../ProMetadataPolicy.md) `MP` determines how a `proxy` erases an invocation and how it keeps the metadata deduced from the contained type. It governs the size of a `proxy` and the indirections an invocation performs, and it is substituted into any [`proxy_dependent_signature`](../proxy_dependent_signature.md) declared by `F`. It does not otherwise change the behavior of a convention or a reflection. The metadata type depends on `MP`, so a `proxy` converts only to a `proxy` with the same metadata policy. See [`compact_metadata`](../compact_metadata.md) for the metadata policies provided by the library. + +Any instance of `proxy` at any given point in time either *contains a value* or *does not contain a value*. If a `proxy` *contains a value*, the type of the value shall be a pointer type `P` where [`proxiable`](../proxiable.md) is `true`, and the value is guaranteed to be allocated as part of the `proxy` object footprint, i.e. no dynamic memory allocation occurs. However, `P` may allocate during its construction, depending on its implementation. Let `Cs` be the convention types of `F` and of every super of `F`, reachable via `typename F::super_types` transitively, and `Rs` be the reflection types of `F` and of every such super. -- For each distinct dispatch type `D` among the types `C` in `Cs` where `C::is_direct` is `true`, let `Os...` be the overload types of those conventions with duplicates removed, and `substituted-overload-types...` be [`substituted-overload...`](../ProOverload.md). If `D` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy, D, substituted-overload-types...`, `typename D::template accessor, D, substituted-overload-types...>` is inherited by `proxy`. -- For each type `R` in `Rs`, if `R::is_direct` is `true` and `typename R::reflector_type` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy, typename R::reflector_type`, `typename R::reflector_type::template accessor, typename R::reflector_type` is inherited by `proxy`. +- For each distinct dispatch type `D` among the types `C` in `Cs` where `C::is_direct` is `true`, let `Os...` be the overload types of those conventions with duplicates removed, and `substituted-overload-types...` be [`substituted-overload...`](../ProOverload.md). If `D` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy, D, substituted-overload-types...`, `typename D::template accessor, D, substituted-overload-types...>` is inherited by `proxy`. +- For each type `R` in `Rs`, if `R::is_direct` is `true` and `typename R::reflector_type` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy, typename R::reflector_type`, `typename R::reflector_type::template accessor, typename R::reflector_type` is inherited by `proxy`. -*Since 5.0.0*: `Cs` and `Rs` include the conventions and reflections of the supers of `F`, and the accessor of a dispatch type is formed from the overload types of every convention in `Cs` sharing that dispatch type, rather than from a single convention. +*Since 5.0.0*: `Cs` and `Rs` include the conventions and reflections of the supers of `F`, and the accessor of a dispatch type is formed from the overload types of every convention in `Cs` sharing that dispatch type, rather than from a single convention. `proxy` also takes a metadata policy. ## Member Types -| Name | Description | -| ---------------------------------- | ----------- | -| `facade_type`
*(since 3.3.1)* | `F` | +| Name | Description | +| ------------------------------------------- | ----------- | +| `facade_type`
*(since 3.3.1)* | `F` | +| `metadata_policy_type`
*(since 5.0.0)* | `MP` | ## Member Functions diff --git a/docs/spec/proxy/assignment.md b/docs/spec/proxy/assignment.md index cd3dcc96..91b0e87b 100644 --- a/docs/spec/proxy/assignment.md +++ b/docs/spec/proxy/assignment.md @@ -26,7 +26,7 @@ proxy& operator=(proxy&& rhs) // (4) (since 5.0.0) template -proxy& operator=(const proxy& rhs) +proxy& operator=(const proxy& rhs) noexcept(F::copyability >= constraint_level::nothrow && F::destructibility >= constraint_level::nothrow) requires(F::copyability >= constraint_level::nontrivial && @@ -34,7 +34,7 @@ proxy& operator=(const proxy& rhs) // (5) (since 5.0.0) template -proxy& operator=(proxy&& rhs) +proxy& operator=(proxy&& rhs) noexcept(F::relocatability >= constraint_level::nothrow && F::destructibility >= constraint_level::nothrow) requires(F::relocatability >= constraint_level::nontrivial && @@ -57,7 +57,7 @@ Assigns a new value to `proxy` or destroys the contained value. - `(3)` Move assignment operator moves the contained value of `rhs` to `*this`. If `rhs` does not contain a value, it destroys the contained value of `*this` (if any). If the move construction throws when `F::relocatability == constraint_level::nontrivial`, `*this` does not contain a value. After move assignment, `rhs` is in a valid state with an unspecified value. The move assignment operator does not participate in overload resolution when `F::copyability == constraint_level::trivial`, falling back to the trivial copy assignment operator. - `(4)` Converting copy assignment operator copies the contained value of `rhs` to `*this`, as if by constructing a `proxy` from `rhs` and assigning it. If `rhs` does not contain a value, it destroys the contained value of `*this` (if any). Participates in overload resolution only if `F2` is not `F` and `F` is a super of `F2`, reachable via `typename F2::super_types` transitively. - `(5)` Converting move assignment operator moves the contained value of `rhs` to `*this`. If `rhs` does not contain a value, it destroys the contained value of `*this` (if any). If the move construction throws when `F::relocatability == constraint_level::nontrivial`, `*this` does not contain a value. After the assignment, `rhs` does not contain a value. Participates in overload resolution only if `F2` is not `F` and `F` is a super of `F2`, reachable via `typename F2::super_types` transitively. The converting move assignment operator does not participate in overload resolution when `F::copyability == constraint_level::trivial`, falling back to `(4)`. -- `(6)` Let `VP` be `std::decay_t

`. Sets the contained value to an object of type `VP`, direct-non-list-initialized with `std::forward

(ptr)`. Participates in overload resolution only if `VP` is not a specialization of `proxy` and is a pointer-like type eligible for `proxy` (see [*ProFacade* requirements](../ProFacade.md)). *Since 3.3.0*: If [`proxiable`](../proxiable.md) is `false`, the program is ill-formed and a diagnostic is generated. +- `(6)` Let `VP` be `std::decay_t

`. Sets the contained value to an object of type `VP`, direct-non-list-initialized with `std::forward

(ptr)`. Participates in overload resolution only if `VP` is not a specialization of `proxy` and is a pointer-like type eligible for `proxy` (see [*ProFacade* requirements](../ProFacade.md)). *Since 3.3.0*: If [`proxiable`](../proxiable.md) is `false`, the program is ill-formed and a diagnostic is generated. ## Return Value diff --git a/docs/spec/proxy/constructor.md b/docs/spec/proxy/constructor.md index 344508dd..6dd80669 100644 --- a/docs/spec/proxy/constructor.md +++ b/docs/spec/proxy/constructor.md @@ -1,4 +1,4 @@ -# `proxy::proxy` +# `proxy::proxy` ```cpp // (1) @@ -21,13 +21,13 @@ proxy(proxy&& rhs) // (4) (since 5.0.0) template -proxy(const proxy& rhs) +proxy(const proxy& rhs) noexcept(F::copyability >= constraint_level::nothrow) requires(F::copyability >= constraint_level::nontrivial); // (5) (since 5.0.0) template -proxy(proxy&& rhs) +proxy(proxy&& rhs) noexcept(F::relocatability >= constraint_level::nothrow) requires(F::relocatability >= constraint_level::nontrivial && F::copyability != constraint_level::trivial); @@ -57,22 +57,22 @@ Creates a new `proxy`. - `(1)` Default constructor and the constructor taking `nullptr` construct a `proxy` that does not contain a value. - `(2)` Copy constructor constructs a `proxy` whose contained value is that of `rhs` if `rhs` contains a value, or otherwise, constructs a `proxy` that does not contain a value. As per the `requires` clause, the copy constructor is trivial when `F::copyability == constraint_level::trivial`. - `(3)` Move constructor constructs a `proxy` whose contained value is that of `rhs` if `rhs` contains a value, or otherwise, constructs a `proxy` that does not contain a value. `rhs` is in a valid but unspecified state after move construction. As per the `requires` clause, the move constructor does not participate in overload resolution when `F::copyability == constraint_level::trivial`, so that a move construction falls back to the trivial copy constructor. -- `(4)` Converting copy constructor constructs a `proxy` whose contained value is a copy of that of `rhs` if `rhs` contains a value, or otherwise, constructs a `proxy` that does not contain a value. Participates in overload resolution only if `F2` is not `F` and `F` is a super of `F2`, reachable via `typename F2::super_types` transitively. +- `(4)` Converting copy constructor constructs a `proxy` whose contained value is a copy of that of `rhs` if `rhs` contains a value, or otherwise, constructs a `proxy` that does not contain a value. Participates in overload resolution only if `F2` is not `F` and `F` is a super of `F2`, reachable via `typename F2::super_types` transitively. `rhs` has the metadata policy of `*this`, because the metadata type of a `proxy` depends on its metadata policy (see [*ProMetadataPolicy* requirements](../ProMetadataPolicy.md)). - `(5)` Converting move constructor constructs a `proxy` whose contained value is that of `rhs` if `rhs` contains a value, or otherwise, constructs a `proxy` that does not contain a value. `rhs` does not contain a value after the conversion. Participates in overload resolution only if `F2` is not `F` and `F` is a super of `F2`, reachable via `typename F2::super_types` transitively. As per the `requires` clause, the converting move constructor does not participate in overload resolution when `F::copyability == constraint_level::trivial`, so that a conversion from an rvalue falls back to `(4)`. - `(6)` Let `VP` be `std::decay_t

`. Constructs a `proxy` whose contained value is of type `VP`, direct-non-list-initialized with `std::forward

(ptr)`. Participates in overload resolution only if `VP` is not a specialization of `proxy` and is a pointer-like type eligible for `proxy` (see [*ProFacade* requirements](../ProFacade.md)). - `(7)` Constructs a `proxy` whose contained value is of type `P`, direct-non-list-initialized with `std::forward(args)...`. Participates in overload resolution only if `P` is a pointer-like type eligible for `proxy`. - `(8)` Constructs a `proxy` whose contained value is of type `P`, direct-non-list-initialized with `il, std::forward(args)...`. Participates in overload resolution only if `P` is a pointer-like type eligible for `proxy`. -*Since 3.3.0*: For `(6-8)`, if [`proxiable, F>`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated. +*Since 3.3.0*: For `(6-8)`, if [`proxiable, F, MP>`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated. ## Comparing with Other Standard Polymorphic Wrappers -The constructors of `proxy` are similar to but have certain differences from other polymorphic wrappers in the standard, specifically, [`std::any`](https://en.cppreference.com/w/cpp/utility/any/any), and [`std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function/move_only_function). +The constructors of `proxy` are similar to but have certain differences from other polymorphic wrappers in the standard, specifically, [`std::any`](https://en.cppreference.com/w/cpp/utility/any/any), and [`std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function/move_only_function). [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function/function) was introduced in C++11. Comparing its constructors with `proxy`: - It forces the target type to be copy constructible, even if its copy constructor is not used in a certain context (which motivated the introduction of `std::move_only_function` in C++23). -- It only supports `Callable` types, while `proxy` supports any pointer type that satisfies [`proxiable`](../proxiable.md). +- It only supports `Callable` types, while `proxy` supports any pointer type that satisfies [`proxiable`](../proxiable.md). - It does not have overloads that take `std::in_place_type_t` to construct a value in-place. - It does not have a conditional default copy constructor, which is efficient for trivial types. - It used to have several overloads that took an additional allocator, 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". Although the constructors of `proxy` do not explicitly take custom allocator types, we believe this is a useful scenario and provided full support via [`allocate_proxy`](../allocate_proxy.md). @@ -89,7 +89,7 @@ The constructors of `proxy` are similar to but have certain differences from [`std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function/move_only_function) was introduced in C++23. Comparing its constructors with `proxy`: - As its name suggests, it is not copyable at all. `proxy` is conditionally copyable depending on the implementation of the given facade type `F`. -- Similar with `std::function`, it only supports `Callable` types, while `proxy` support any pointer type that satisfies [`proxiable`](../proxiable.md). +- Similar with `std::function`, it only supports `Callable` types, while `proxy` support any pointer type that satisfies [`proxiable`](../proxiable.md). - Similar with `std::any`, it does not support allocators. - Similar with `std::any`, in the overloads that take `std::in_place_type_t` to construct a value in-place, the value type is obtained via `std::decay_t` rather than bare `T`, which complicates the semantics and we do not believe is useful. @@ -146,3 +146,4 @@ int main() { ## See Also - [concept `proxiable`](../proxiable.md) +- [class `compact_metadata`
class `inline_metadata`](../compact_metadata.md) diff --git a/docs/spec/proxy/destructor.md b/docs/spec/proxy/destructor.md index 1a846cd6..5a0fa797 100644 --- a/docs/spec/proxy/destructor.md +++ b/docs/spec/proxy/destructor.md @@ -1,4 +1,4 @@ -# `proxy::~proxy` +# `proxy::~proxy` ```cpp ~proxy() requires(F::destructibility == constraint_level::trivial) diff --git a/docs/spec/proxy/emplace.md b/docs/spec/proxy/emplace.md index 587c00cf..94da5dec 100644 --- a/docs/spec/proxy/emplace.md +++ b/docs/spec/proxy/emplace.md @@ -26,7 +26,7 @@ First, the current contained value (if any) is destroyed as if by calling [reset - `(1)` Sets the contained value to an object of type `P`, direct-non-list-initialized with `std::forward(args)...`. Participates in overload resolution only if `P` is a pointer-like type eligible for `proxy` (see [*ProFacade* requirements](../ProFacade.md)). - `(2)` Sets the contained value to an object of type `P`, direct-non-list-initialized with `il, std::forward(args)...`. Participates in overload resolution only if `P` is a pointer-like type eligible for `proxy`. -*Since 3.3.0*: For `(1-2)`, if [`proxiable`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated. +*Since 3.3.0*: For `(1-2)`, if [`proxiable`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated. ## Return Value diff --git a/docs/spec/proxy/friend_invoke.md b/docs/spec/proxy/friend_invoke.md index ead41933..6793a209 100644 --- a/docs/spec/proxy/friend_invoke.md +++ b/docs/spec/proxy/friend_invoke.md @@ -1,19 +1,19 @@ -# Function template `invoke` (`proxy`) +# Function template `invoke` (`proxy`) > Since: 4.1.0 ```cpp template -return-type-of invoke(proxy& p, Args&&... args); +return-type-of invoke(proxy& p, Args&&... args); template -return-type-of invoke(const proxy& p, Args&&... args); +return-type-of invoke(const proxy& p, Args&&... args); template -return-type-of invoke(proxy&& p, Args&&... args); +return-type-of invoke(proxy&& p, Args&&... args); template -return-type-of invoke(const proxy&& p, Args&&... args); +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`. +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. @@ -21,11 +21,11 @@ There shall be a convention type `Conv` defined in the convention types of `F` o - `Conv::is_direct` is `true`, and - `typename Conv::dispatch_type` is `D`, and -- [`substituted-overload`](../ProOverload.md)`` is `O`. +- [`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. +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/friend_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 diff --git a/docs/spec/proxy/friend_operator_equality.md b/docs/spec/proxy/friend_operator_equality.md index df1d16bb..15818b31 100644 --- a/docs/spec/proxy/friend_operator_equality.md +++ b/docs/spec/proxy/friend_operator_equality.md @@ -1,4 +1,4 @@ -# Function `operator==` (`proxy`) +# Function `operator==` (`proxy`) ```cpp friend bool operator==(const proxy& lhs, std::nullptr_t) noexcept; @@ -6,7 +6,7 @@ friend bool operator==(const proxy& lhs, std::nullptr_t) noexcept; Checks whether `lhs` contains a value by comparing it with `nullptr`. A `proxy` that does not contain a value compares equal to `nullptr`; otherwise, it compares non-equal. -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. +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. The `!=` operator is [synthesized](https://en.cppreference.com/w/cpp/language/default_comparisons) from `operator==`. diff --git a/docs/spec/proxy/friend_reflect.md b/docs/spec/proxy/friend_reflect.md index 9bf04cd1..108974a8 100644 --- a/docs/spec/proxy/friend_reflect.md +++ b/docs/spec/proxy/friend_reflect.md @@ -1,13 +1,13 @@ -# Function template `reflect` (`proxy`) +# Function template `reflect` (`proxy`) > Since: 4.1.0 ```cpp template -const R& reflect(const proxy& p) noexcept; +const R& reflect(const proxy& p) noexcept; ``` -Acquires reflection information of the contained type of a `proxy`, through a *direct* reflection. +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. @@ -18,9 +18,9 @@ There shall be a reflection type `Refl` defined in the reflection types of `F` o 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. +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/friend_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 diff --git a/docs/spec/proxy/friend_swap.md b/docs/spec/proxy/friend_swap.md index fdc8f5b2..a7c4622a 100644 --- a/docs/spec/proxy/friend_swap.md +++ b/docs/spec/proxy/friend_swap.md @@ -1,4 +1,4 @@ -# Function `swap` (`proxy`) +# Function `swap` (`proxy`) ```cpp friend void swap(proxy& lhs, proxy& rhs) noexcept(noexcept(lhs.swap(rhs))) @@ -7,7 +7,7 @@ friend void swap(proxy& lhs, proxy& rhs) noexcept(noexcept(lhs.swap(rhs))) Overloads the [std::swap](https://en.cppreference.com/w/cpp/algorithm/swap) algorithm for `proxy`. Exchanges the state of `lhs` with that of `rhs`. Effectively calls `lhs.swap(rhs)`. -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. +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. ## Example diff --git a/docs/spec/proxy/indirection.md b/docs/spec/proxy/indirection.md index a1dd8ef0..780b9bbf 100644 --- a/docs/spec/proxy/indirection.md +++ b/docs/spec/proxy/indirection.md @@ -2,20 +2,20 @@ ```cpp // (1) -proxy_indirect_accessor* operator->() noexcept; -const proxy_indirect_accessor* operator->() const noexcept; +proxy_indirect_accessor* operator->() noexcept; +const proxy_indirect_accessor* operator->() const noexcept; // (2) -proxy_indirect_accessor& operator*() & noexcept; -const proxy_indirect_accessor& operator*() const& noexcept; -proxy_indirect_accessor&& operator*() && noexcept; -const proxy_indirect_accessor&& operator*() const&& noexcept; +proxy_indirect_accessor& operator*() & noexcept; +const proxy_indirect_accessor& operator*() const& noexcept; +proxy_indirect_accessor&& operator*() && noexcept; +const proxy_indirect_accessor&& operator*() const&& noexcept; ``` These operators access the accessors of the indirect conventions, as if dereferencing the contained value. -- `(1)` Returns a pointer to the `proxy_indirect_accessor`. -- `(2)` Returns a reference to the `proxy_indirect_accessor`. +- `(1)` Returns a pointer to the `proxy_indirect_accessor`. +- `(2)` Returns a reference to the `proxy_indirect_accessor`. The behavior is undefined if `*this` does not contain a value. diff --git a/docs/spec/proxy_dependent_signature.md b/docs/spec/proxy_dependent_signature.md index f1004025..7e024934 100644 --- a/docs/spec/proxy_dependent_signature.md +++ b/docs/spec/proxy_dependent_signature.md @@ -1,20 +1,24 @@ -# Class template `facade_aware_overload_t` +# Class template `proxy_dependent_signature` > Header: `proxy.h` > Module: `proxy` > Namespace: `pro::inline v5` -> Since: 3.2.1 +> Since: 5.0.0 ```cpp -template