diff --git a/docs/spec/.pages b/docs/spec/.pages index fb90bf3..6c5f5f2 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/ProBasicMeta.md b/docs/spec/ProBasicMeta.md deleted file mode 100644 index 44199ce..0000000 --- a/docs/spec/ProBasicMeta.md +++ /dev/null @@ -1,21 +0,0 @@ -# Named requirements: *ProBasicMeta* - -> 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`). - -| Expressions | Semantics | -| ----------- | ------------------------------------------------------------ | -| `M()` | Creates an object of type `M` holding unspecified metadata, shall not throw. | -| `M(cm)` | Creates an object of type `M` holding the metadata of `cm`, shall not throw. | -| `m = cm` | Replaces the metadata of `m` with the metadata of `cm`, shall not throw. | -| `m.~M()` | Destroys the object `m`, shall not throw. | - -## 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. - -## See Also - -- [*ProBasicReflection* requirements](ProBasicReflection.md) -- [*ProMeta* requirements](ProMeta.md) diff --git a/docs/spec/ProBasicMetadata.md b/docs/spec/ProBasicMetadata.md new file mode 100644 index 0000000..0b0a362 --- /dev/null +++ b/docs/spec/ProBasicMetadata.md @@ -0,0 +1,22 @@ +# Named requirements: *ProBasicMetadata* + +> Since: 5.0.0 + +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 | +| ----------- | ------------------------------------------------------------ | +| `M()` | Creates an object of type `M` holding unspecified metadata, shall not throw. | +| `M(cm)` | Creates an object of type `M` holding the metadata of `cm`, shall not throw. | +| `m = cm` | Replaces the metadata of `m` with the metadata of `cm`, shall not throw. | +| `m.~M()` | Destroys the object `m`, shall not throw. | + +## Notes + +"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) +- [*ProMetadata* requirements](ProMetadata.md) +- [*ProMetadataPolicy* requirements](ProMetadataPolicy.md) diff --git a/docs/spec/ProBasicReflection.md b/docs/spec/ProBasicReflection.md index e845dfd..293c0fa 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 2d2ac7c..1bf6c32 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 22da818..36464e3 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/ProMeta.md b/docs/spec/ProMetadata.md similarity index 52% rename from docs/spec/ProMeta.md rename to docs/spec/ProMetadata.md index 30dbccf..6d16b60 100644 --- a/docs/spec/ProMeta.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 0000000..4d26f42 --- /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 3f02d53..40010bc 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 7878144..9fbdc9f 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 4254cd1..390d201 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 c2436a1..e0b75c9 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 84b90dd..b40aed8 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 2a5eb07..eb77e87 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 0000000..3d6fd69 --- /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/facade_aware_overload_t.md b/docs/spec/facade_aware_overload_t.md deleted file mode 100644 index f100402..0000000 --- a/docs/spec/facade_aware_overload_t.md +++ /dev/null @@ -1,57 +0,0 @@ -# Class template `facade_aware_overload_t` - -> Header: `proxy.h` -> Module: `proxy` -> Namespace: `pro::inline v5` -> Since: 3.2.1 - -```cpp -template