From 2acd69920555af6e67f513733897cd518dfd3fda Mon Sep 17 00:00:00 2001 From: Mingxin Wang Date: Thu, 3 Sep 2026 21:17:04 -0400 Subject: [PATCH] Add super facades add_facade copied F's conventions and reflections into the built facade. The two facades then shared behavior but had unrelated metadata, so converting a proxy of one to a proxy of the other needed an explicit substitution convention and an indirect call to translate. Give a facade a super_types list. add_facade records F there instead of copying, and the metadata of the built facade embeds the metadata of each super, so const proxy_meta& converts to const proxy_meta&. proxy gains converting constructors and assignment operators guarded on exactly that conversion: the metadata is carried over directly, and only the contained value is copied or relocated. A convention whose overload is a facade_aware_overload_t is the exception to "not copied": its overload depends on the facade it is built into, so it is also checked and made available against the built facade. That is what lets as_view declared on a super yield a proxy_view of the built facade rather than of the super. Accessors are formed from the conventions of the facade and of every super, regrouped per dispatch type, so an overload set spanning a super and the facade that derives from it stays a single overload set. observer_facade and weak_facade map super_types through themselves, so view-ness and weak-ness are preserved across a conversion to a super. Assignment also grows the fallbacks a facade that forbids relocation needs: with no move assignment to commit a temporary with, assignment empties *this up front instead of failing to compile. add_facade, deprecated since 4.1.0, is removed. The second parameter of add_facade, deprecated since 4.1.0, is retained and ignored: a proxy of the built facade already converts to a proxy because F is a super. add_facade_with_substitution and substitution_dispatch are unchanged and still take precedence where both apply; they are addressed in a follow-up. --- docs/spec/ProBasicFacade.md | 19 +- docs/spec/ProFacade.md | 21 +- docs/spec/basic_facade_builder/.pages | 2 +- docs/spec/basic_facade_builder/README.md | 14 +- .../basic_facade_builder/add_convention.md | 12 +- docs/spec/basic_facade_builder/add_facade.md | 24 +- .../basic_facade_builder/add_reflection.md | 12 +- docs/spec/basic_facade_builder/build.md | 11 +- docs/spec/proxy/README.md | 4 +- docs/spec/proxy/assignment.md | 23 +- docs/spec/proxy/constructor.md | 29 +- docs/spec/proxy/friend_invoke.md | 2 +- docs/spec/proxy/friend_reflect.md | 2 +- docs/spec/proxy_indirect_accessor/README.md | 4 +- .../proxy_indirect_accessor/friend_invoke.md | 2 +- .../proxy_indirect_accessor/friend_reflect.md | 2 +- docs/spec/proxy_invoke.md | 4 +- docs/spec/proxy_view.md | 11 +- docs/spec/weak_proxy.md | 11 +- include/proxy/v4/detail/core.h | 431 ++++++++++++------ include/proxy/v4/detail/facade_creation.h | 72 ++- tests/proxy_dispatch_tests.cpp | 31 ++ tests/proxy_invocation_tests.cpp | 45 ++ tests/proxy_lifetime_tests.cpp | 103 ++++- tests/proxy_traits_tests.cpp | 205 +++++++-- tests/proxy_view_tests.cpp | 42 ++ tests/utils.h | 32 ++ 27 files changed, 876 insertions(+), 294 deletions(-) diff --git a/docs/spec/ProBasicFacade.md b/docs/spec/ProBasicFacade.md index 2063bc69..c9a73b0d 100644 --- a/docs/spec/ProBasicFacade.md +++ b/docs/spec/ProBasicFacade.md @@ -2,15 +2,16 @@ A type `F` meets the *ProBasicFacade* requirements if the following expressions are well-formed and have the specified semantics. -| Expressions | Semantics | -| ------------------------------ | ------------------------------------------------------------ | -| `typename F::convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct types `Cs`. Each type `C` in `Cs` shall meet the [*ProBasicConvention* requirements](ProBasicConvention.md). | -| `typename F::reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct types `Rs`. Each type `R` in `Rs` shall meet the [*ProBasicReflection* requirements](ProBasicReflection.md). | -| `F::max_size` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `std::size_t` that defines the maximum size of a pointer type. Shall be greater than `0` and a multiple of `F::max_align`. | -| `F::max_align` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `std::size_t` that defines the maximum alignment of a pointer type. Shall be a power of `2`. | -| `F::copyability` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type [`constraint_level`](constraint_level.md) that defines the required copyability of a pointer type. | -| `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 a pointer type. | -| `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 a pointer type. | +| 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 *ProBasicFacade* requirements, and shall be no more conservative than `F`, that is: `F::max_size <= S::max_size`, `F::max_align <= S::max_align`, `F::copyability >= S::copyability`, `F::relocatability >= S::relocatability`, and `F::destructibility >= S::destructibility`. | +| `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 [*ProBasicConvention* requirements](ProBasicConvention.md). | +| `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 [*ProBasicReflection* requirements](ProBasicReflection.md). | +| `F::max_size` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `std::size_t` that defines the maximum size of a pointer type. Shall be greater than `0` and a multiple of `F::max_align`. | +| `F::max_align` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `std::size_t` that defines the maximum alignment of a pointer type. Shall be a power of `2`. | +| `F::copyability` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type [`constraint_level`](constraint_level.md) that defines the required copyability of a pointer type. | +| `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 a pointer type. | +| `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 a pointer type. | Each of `F::copyability`, `F::relocatability`, and `F::destructibility` shall be exactly one of the four enumerators of `constraint_level` (`none`, `nontrivial`, `nothrow`, `trivial`). diff --git a/docs/spec/ProFacade.md b/docs/spec/ProFacade.md index 60221a43..22da818c 100644 --- a/docs/spec/ProFacade.md +++ b/docs/spec/ProFacade.md @@ -2,15 +2,18 @@ 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. -| Expressions | Semantics | -| ------------------------------ | ------------------------------------------------------------ | -| `typename F::convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct types `Cs`. Each type `C` in `Cs` shall meet the [*ProConvention* requirements](ProConvention.md) of `P`. | -| `typename F::reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct 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)`. | -| `F::copyability` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type [`constraint_level`](constraint_level.md) that defines the required copyability of `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`. | +| 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::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)`. | +| `F::copyability` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type [`constraint_level`](constraint_level.md) that defines the required copyability of `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 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/basic_facade_builder/.pages b/docs/spec/basic_facade_builder/.pages index 4ed3625d..0357bcb0 100644 --- a/docs/spec/basic_facade_builder/.pages +++ b/docs/spec/basic_facade_builder/.pages @@ -1,8 +1,8 @@ nav: - basic_facade_builder: README.md - add_convention
add_indirect_convention
add_direct_convention: add_convention.md - - add_facade_with_substitution: add_facade_with_substitution.md - add_facade: add_facade.md + - add_facade_with_substitution: add_facade_with_substitution.md - add_reflection
add_indirect_reflection
add_direct_reflection: add_reflection.md - add_skill: add_skill.md - build: build.md diff --git a/docs/spec/basic_facade_builder/README.md b/docs/spec/basic_facade_builder/README.md index 50a7863d..eaa3c775 100644 --- a/docs/spec/basic_facade_builder/README.md +++ b/docs/spec/basic_facade_builder/README.md @@ -15,18 +15,20 @@ constexpr constraint_level default-cl = static_cast( Given a [facade](../facade.md) type `F`, any meaningful value of `F::max_size` and `F::max_align` is less than *default-size*; any meaningful value of `F::copyability`, `F::relocatability`, and `F::destructibility` is greater than *default-cl*. ```cpp -template +template class basic_facade_builder; using facade_builder = - basic_facade_builder, std::tuple<>, default-size, default-size, - default-cl, default-cl, default-cl>; + basic_facade_builder, std::tuple<>, std::tuple<>, default-size, + default-size, default-cl, default-cl, default-cl>; ``` `basic_facade_builder` provides a member type `build` that compiles the template parameters into a [`facade`](../facade.md) type. The template parameters can be modified via various member alias templates that specify `basic_facade_builder` with the modified template parameters. +*Since 5.0.0*: `Ss` is added to the template parameters, holding the supers accumulated by [`add_facade`](add_facade.md). + ## Member Types | Name | Description | @@ -38,8 +40,8 @@ using facade_builder = | Name | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | | [`add_convention`
`add_indirect_convention`
`add_direct_convention`](add_convention.md) | Adds a convention to the template parameters | -| [`add_facade_with_substitution`](add_facade_with_substitution.md) | Adds a facade to the template parameters, together with [substitution](../substitution_dispatch/README.md) support | | [`add_facade`](add_facade.md) | Adds a facade to the template parameters | +| [`add_facade_with_substitution`](add_facade_with_substitution.md) | Adds a facade to the template parameters, together with [substitution](../substitution_dispatch/README.md) support | | [`add_reflection`
`add_indirect_reflection`
`add_direct_reflection`](add_reflection.md) | Adds a reflection to the template parameters | | [`add_skill`](add_skill.md) | Adds a custom skill | | [`restrict_layout`](restrict_layout.md) | Specifies maximum `MaxSize` and `MaxAlign` in the template parameters | diff --git a/docs/spec/basic_facade_builder/add_convention.md b/docs/spec/basic_facade_builder/add_convention.md index c432c9d6..2e43c3d0 100644 --- a/docs/spec/basic_facade_builder/add_convention.md +++ b/docs/spec/basic_facade_builder/add_convention.md @@ -11,27 +11,23 @@ template requires(/* see below */) using add_direct_convention = basic_facade_builder; ``` -The alias templates `add_convention`, `add_indirect_convention`, and `add_direct_convention` of `basic_facade_builder` add convention types to the template parameters. The expression inside `requires` is equivalent to `sizeof...(Os) > 0u` and each type in `Os` meets the [*ProOverload* requirements](../ProOverload.md). Let `F` be a facade type, +The alias templates `add_convention`, `add_indirect_convention`, and `add_direct_convention` of `basic_facade_builder` add convention types to the template parameters. The expression inside `requires` is equivalent to `sizeof...(Os) > 0u` and each type in `Os` meets the [*ProOverload* requirements](../ProOverload.md). - `add_convention` is equivalent to `add_indirect_convention`. -- `add_indirect_convention` merges an implementation-defined convention type `IC` into `Cs` for each type `O` in `Os`, where: +- `add_indirect_convention` appends an implementation-defined convention type `IC` to `Cs` for each type `O` in `Os`, where: - `IC::is_direct` is `false`. - `typename IC::dispatch_type` is `D`. - `typename IC::overload_type` is `O`. -- `add_direct_convention` merges an implementation-defined convention type `IC` into `Cs` for each type `O` in `Os`, where: +- `add_direct_convention` appends an implementation-defined convention type `IC` to `Cs` for each type `O` in `Os`, where: - `IC::is_direct` is `true`. - `typename IC::dispatch_type` is `D`. - `typename IC::overload_type` is `O`. -When `Cs` already contains a convention type identical to `IC`, the template parameters shall not change. - -Let `F` be a facade type. The accessor a convention contributes to a [`proxy`](../proxy/README.md) of `F` is formed per dispatch type rather than per convention: let `Gs` be the types in `Cs` that share `IC::is_direct` and `typename IC::dispatch_type`, and `GOs` be their `overload_type`s in order of first appearance. The accessor is `typename D::template accessor, D, `[`substituted-overload`](../ProOverload.md)`...>` when `IC::is_direct` is `false`, or `typename D::template accessor, D, `[`substituted-overload`](../ProOverload.md)`...>` when it is `true`, if applicable. - *Since 5.0.0*: each type in `Os` produces its own convention type, rather than one convention type carrying a tuple-like `overload_types`. ## Notes -Adding duplicated combinations of some dispatch type and overload type is well-defined (either directly via `add_convention`, `add_indirect_convention`, `add_direct_convention`, or indirectly via [`add_facade`](add_facade.md)), and does not have side-effects to [`build`](build.md) at either compile-time or runtime. +Adding duplicated combinations of some dispatch type and overload type is well-defined (either directly via `add_convention`, `add_indirect_convention`, `add_direct_convention`, or indirectly via [`add_facade`](add_facade.md)). While such duplicates change the type produced by [`build`](build.md), they do not have side-effects on a [`proxy`](../proxy/README.md) of that facade at either compile-time or runtime. ## Example diff --git a/docs/spec/basic_facade_builder/add_facade.md b/docs/spec/basic_facade_builder/add_facade.md index 07f4c10a..6e3b9622 100644 --- a/docs/spec/basic_facade_builder/add_facade.md +++ b/docs/spec/basic_facade_builder/add_facade.md @@ -1,26 +1,30 @@ # `basic_facade_builder::add_facade` ```cpp -template +template using add_facade = basic_facade_builder; ``` -The alias template `add_facade` of `basic_facade_builder` adds a [facade](../facade.md) type into the template parameters. Specifically, it +The alias template `add_facade` of `basic_facade_builder` adds a [facade](../facade.md) type into the template parameters. Specifically, it -- merges `typename F::convention_types` into `Cs`, and -- merges `typename F::reflection_types` into `Rs`, and +- adds `F` into `Ss`, and - sets `MaxSize` to `std::min(MaxSize, F::max_size)`, and - sets `MaxAlign` to `std::min(MaxAlign, F::max_align)`, and - sets `Copyability` to `std::max(Copyability, F::copyability)`, and - sets `Relocatability` to `std::max(Relocatability, F::relocatability)`, and -- sets `Destructibility` to `std::max(Destructibility, F::destructibility)`, and -- optionally, merges a direct convention of [`substitution_dispatch`](../substitution_dispatch/README.md) into `Cs` when `WithSubstitution` is `true` *(deprecated since 4.1.0: use [`add_facade_with_substitution`](add_facade_with_substitution.md) instead)*. +- sets `Destructibility` to `std::max(Destructibility, F::destructibility)`. + +*Since 5.0.0*: `F` is added to `Ss`, rather than having its conventions and reflections merged into `Cs` and `Rs`. `Unused` has no effect. ## Notes -Adding a facade type that contains duplicated convention or reflection types already defined in `Cs` or `Rs` is well-defined and does not have side effects on [`build`](build.md) at either compile-time or runtime. By default, `WithSubstitution` is `false`, which guarantees minimal binary size in code generation. However, substitution is helpful when an API requires backward compatibility. Users can opt-in to this feature via [`add_facade_with_substitution`](add_facade_with_substitution.md), at the cost of potentially a slightly larger binary size. +The conventions and reflections of `F` are not copied into `Cs` or `Rs`. They are reached through the super. Adding the same facade more than once, or redeclaring a convention that a super already provides, is well-defined and does not have side effects on [`build`](build.md) at either compile-time or runtime. + +A convention whose overload is a specialization of [`facade_aware_overload_t`](../facade_aware_overload_t.md) is the exception: its overload depends on the facade it is built into, so it is also checked and made available against the built facade, not only against the super that declares it. [`proxiable`](../proxiable.md) therefore requires the pointer type to satisfy both substitutions, and a failure of either is diagnosed. This is what lets a skill such as [`as_view`](../skills_as_view.md) declared on a super yield a [`proxy_view`](../proxy_view.md) of the built facade rather than of the super. + +The metadata of the built facade embeds the metadata of each super, so that converting to a `proxy` 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)`. -**Deprecated since 4.1.0**: Specifying the `WithSubstitution` parameter as `true` (i.e., `add_facade`) is deprecated. Use [`add_facade_with_substitution`](add_facade_with_substitution.md)`` instead. The single-argument form `add_facade` is not affected. +A [`proxy`](../proxy/README.md) of the built facade converts to a `proxy`, subject to the copyability and relocatability of `F`. ## Example @@ -52,7 +56,7 @@ struct StringDictionary struct MutableStringDictionary : pro::facade_builder // - ::add_facade_with_substitution // + ::add_facade // ::add_convention // ::build {}; @@ -70,7 +74,7 @@ int main() { auto p2 = p1; // Performs a deep copy p2->emplace(456, "trivial"); - // Performs a substitution from an rvalue reference + // Converts to a proxy of the super from an rvalue reference pro::proxy p3 = std::move(p2); std::cout << p1->size() << "\n"; // Prints "1" std::cout << p1->at(123) << "\n"; // Prints "lalala" diff --git a/docs/spec/basic_facade_builder/add_reflection.md b/docs/spec/basic_facade_builder/add_reflection.md index 3a02def6..59eabbce 100644 --- a/docs/spec/basic_facade_builder/add_reflection.md +++ b/docs/spec/basic_facade_builder/add_reflection.md @@ -11,23 +11,25 @@ template using add_direct_reflection = basic_facade_builder; ``` -The alias templates `add_reflection`, `add_indirect_reflection` and `add_direct_reflection` of `basic_facade_builder` add reflection types to the template parameters. Specifically, +The alias templates `add_reflection`, `add_indirect_reflection` and `add_direct_reflection` of `basic_facade_builder` add reflection types to the template parameters. Specifically, - `add_reflection` is equivalent to `add_indirect_reflection`. -- `add_indirect_reflection` merges an implementation-defined reflection type `Refl` into `Rs`, where: +- `add_indirect_reflection` appends an implementation-defined reflection type `Refl` to `Rs`, where: - `Refl::is_direct` is `false`. - `typename Refl::reflector_type` is `R`. - `typename Refl::template accessor` is `typename R::template accessor, R>` if applicable. -- `add_direct_reflection` merges an implementation-defined reflection type `Refl` into `Rs`, where: +- `add_direct_reflection` appends an implementation-defined reflection type `Refl` to `Rs`, where: - `Refl::is_direct` is `true`. - `typename Refl::reflector_type` is `R`. - `typename Refl::template accessor` is `typename R::template accessor, R>` if applicable. -When `Rs` already contains `Refl`, the template parameters shall not change. +Reflection types are deduplicated when a [`proxy`](../proxy/README.md) of the built facade is instantiated, not when they are added. + +*Since 5.0.0*: reflection types are appended rather than merged into `Rs`. ## Notes -Adding duplicate reflection types is well-defined, whether done directly via `add_reflection`, `add_indirect_reflection`, `add_direct_reflection`, or indirectly via [`add_facade`](add_facade.md). This process does not affect the behavior of [`build`](build.md) at either compile-time or runtime. +Adding duplicate reflection types is well-defined, whether done directly via `add_reflection`, `add_indirect_reflection`, `add_direct_reflection`, or indirectly via [`add_facade`](add_facade.md). While such duplicates change the type produced by [`build`](build.md), they do not affect a [`proxy`](../proxy/README.md) of that facade at either compile-time or runtime. ## Example diff --git a/docs/spec/basic_facade_builder/build.md b/docs/spec/basic_facade_builder/build.md index 4fa34ae2..6a747f18 100644 --- a/docs/spec/basic_facade_builder/build.md +++ b/docs/spec/basic_facade_builder/build.md @@ -4,14 +4,15 @@ using build = /* see below */; ``` -Specifies a [facade](../facade.md) type deduced from the template parameters of `basic_facade_builder`. +Specifies a [facade](../facade.md) type deduced from the template parameters of `basic_facade_builder`. ## Member Types -| Name | Definition | -| ------------------ | ---------- | -| `convention_types` | `Cs` | -| `reflection_types` | `Rs` | +| Name | Definition | +| ---------------------------------- | ---------- | +| `super_types`
*(since 5.0.0)* | `Ss` | +| `convention_types` | `Cs` | +| `reflection_types` | `Rs` | ## Member Constants diff --git a/docs/spec/proxy/README.md b/docs/spec/proxy/README.md index 4a656316..e7c38d33 100644 --- a/docs/spec/proxy/README.md +++ b/docs/spec/proxy/README.md @@ -13,12 +13,12 @@ Class template `proxy` is a general-purpose polymorphic wrapper for C++ objects. 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. -As per `facade`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. +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`. -*Since 5.0.0*: 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. ## Member Types diff --git a/docs/spec/proxy/assignment.md b/docs/spec/proxy/assignment.md index 8934ce13..27925692 100644 --- a/docs/spec/proxy/assignment.md +++ b/docs/spec/proxy/assignment.md @@ -24,7 +24,24 @@ proxy& operator=(proxy&& rhs) F::destructibility >= constraint_level::nontrivial && F::copyability != constraint_level::trivial); -// (4) +// (4) (since 5.0.0) +template +proxy& operator=(const proxy& rhs) + noexcept(F::copyability >= constraint_level::nothrow && + F::destructibility >= constraint_level::nothrow) + requires(F::copyability >= constraint_level::nontrivial && + F::destructibility >= constraint_level::nontrivial); + +// (5) (since 5.0.0) +template +proxy& operator=(proxy&& rhs) + noexcept(F::relocatability >= constraint_level::nothrow && + F::destructibility >= constraint_level::nothrow) + requires(F::relocatability >= constraint_level::nontrivial && + F::destructibility >= constraint_level::nontrivial && + F::copyability != constraint_level::trivial); + +// (6) template proxy& operator=(P&& ptr) noexcept(std::is_nothrow_constructible_v, P> && @@ -38,7 +55,9 @@ Assigns a new value to `proxy` or destroys the contained value. - `(1)` Destroys the current contained value if it exists. After the call, `*this` does not contain a value. - `(2)` Copy assignment operator copies the contained value of `rhs` to `*this`. If `rhs` does not contain a value, it destroys the contained value of `*this` (if any) as if by `auto(rhs).swap(*this)`. The copy assignment is trivial when `F::copyability == constraint_level::trivial` is `true`. - `(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)` 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. +- `(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). 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. ## Return Value diff --git a/docs/spec/proxy/constructor.md b/docs/spec/proxy/constructor.md index 922bf8f6..d05846ce 100644 --- a/docs/spec/proxy/constructor.md +++ b/docs/spec/proxy/constructor.md @@ -19,18 +19,31 @@ proxy(proxy&& rhs) requires(F::relocatability >= constraint_level::nontrivial && F::copyability != constraint_level::trivial); -// (4) +// (4) (since 5.0.0) +template +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) + noexcept(F::relocatability >= constraint_level::nothrow) + requires(F::relocatability >= constraint_level::nontrivial && + F::copyability != constraint_level::trivial); + +// (6) template proxy(P&& ptr) noexcept(std::is_nothrow_constructible_v, P>) requires(std::is_constructible_v, P>); -// (5) +// (7) template explicit proxy(std::in_place_type_t

, Args&&... args) noexcept(std::is_nothrow_constructible_v) requires(std::is_constructible_v); -// (6) +// (8) template explicit proxy(std::in_place_type_t

, std::initializer_list il, Args&&... args) @@ -44,11 +57,13 @@ 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)` 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)). -- `(5)` 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`. -- `(6)` 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`. +- `(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. +- `(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 `(4-6)`, 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>`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated. ## Comparing with Other Standard Polymorphic Wrappers diff --git a/docs/spec/proxy/friend_invoke.md b/docs/spec/proxy/friend_invoke.md index 2facfe60..ead41933 100644 --- a/docs/spec/proxy/friend_invoke.md +++ b/docs/spec/proxy/friend_invoke.md @@ -17,7 +17,7 @@ Invokes a `proxy` with a specified dispatch type `D`, an overload type `O`, a Let `ptr` be the contained value of `p` with the same cv ref-qualifiers. Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), ptr, static_cast(args)...)`. The behavior is undefined if `p` does not contain a value. -There shall be a convention type `Conv` defined in `typename F::convention_types` where +There shall be a convention type `Conv` defined in the convention types of `F` or of any super of `F`, reachable via `typename F::super_types` transitively, where - `Conv::is_direct` is `true`, and - `typename Conv::dispatch_type` is `D`, and diff --git a/docs/spec/proxy/friend_reflect.md b/docs/spec/proxy/friend_reflect.md index bf74787b..9bf04cd1 100644 --- a/docs/spec/proxy/friend_reflect.md +++ b/docs/spec/proxy/friend_reflect.md @@ -11,7 +11,7 @@ Acquires reflection information of the contained type of a `proxy`, through a Let `P` be the contained type of `p`. Returns a `const` reference of `R` direct-non-list-initialized with [`std::in_place_type

`](https://en.cppreference.com/w/cpp/utility/in_place). The behavior is undefined if `p` does not contain a value. -There shall be a reflection type `Refl` defined in `typename F::reflection_types` where +There shall be a reflection type `Refl` defined in the reflection types of `F` or of any super of `F`, reachable via `typename F::super_types` transitively, where - `Refl::is_direct` is `true`, and - `typename Refl::reflector_type` is `R`. diff --git a/docs/spec/proxy_indirect_accessor/README.md b/docs/spec/proxy_indirect_accessor/README.md index e510dd28..9f2f81ce 100644 --- a/docs/spec/proxy_indirect_accessor/README.md +++ b/docs/spec/proxy_indirect_accessor/README.md @@ -10,12 +10,12 @@ template class proxy_indirect_accessor; ``` -Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. As per `facade`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. +Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. 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 `false`, 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_indirect_accessor, D, substituted-overload-types...`, `typename D::template accessor, D, substituted-overload-types...>` is inherited by `proxy_indirect_accessor`. - For each type `R` in `Rs`, if `R::is_direct` is `false` and `typename R::reflector_type` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy_indirect_accessor, typename R::reflector_type`, `typename R::reflector_type::template accessor, typename R::reflector_type` is inherited by `proxy_indirect_accessor`. -*Since 5.0.0*: 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. ## Member Functions diff --git a/docs/spec/proxy_indirect_accessor/friend_invoke.md b/docs/spec/proxy_indirect_accessor/friend_invoke.md index fb8b015a..ebfbfab4 100644 --- a/docs/spec/proxy_indirect_accessor/friend_invoke.md +++ b/docs/spec/proxy_indirect_accessor/friend_invoke.md @@ -17,7 +17,7 @@ Invokes a `proxy_indirect_accessor` with a specified dispatch type `D`, an ov Let `ptr` be the contained value of the `proxy` object associated to `p` with the same cv ref-qualifiers. Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), *ptr, static_cast(args)...)`. -There shall be a convention type `Conv` defined in `typename F::convention_types` where +There shall be a convention type `Conv` defined in the convention types of `F` or of any super of `F`, reachable via `typename F::super_types` transitively, where - `Conv::is_direct` is `false`, and - `typename Conv::dispatch_type` is `D`, and diff --git a/docs/spec/proxy_indirect_accessor/friend_reflect.md b/docs/spec/proxy_indirect_accessor/friend_reflect.md index 70630c7e..900bad32 100644 --- a/docs/spec/proxy_indirect_accessor/friend_reflect.md +++ b/docs/spec/proxy_indirect_accessor/friend_reflect.md @@ -11,7 +11,7 @@ Acquires reflection information of the contained type of the associated `proxy`, Let `P` be the contained type of the `proxy` object associated to `p`. Returns a `const` reference of `R` direct-non-list-initialized with [`std::in_place_type::element_type>`](https://en.cppreference.com/w/cpp/utility/in_place). -There shall be a reflection type `Refl` defined in `typename F::reflection_types` where +There shall be a reflection type `Refl` defined in the reflection types of `F` or of any super of `F`, reachable via `typename F::super_types` transitively, where - `Refl::is_direct` is `false`, and - `typename Refl::reflector_type` is `R`. diff --git a/docs/spec/proxy_invoke.md b/docs/spec/proxy_invoke.md index dda3a2d1..dd84873a 100644 --- a/docs/spec/proxy_invoke.md +++ b/docs/spec/proxy_invoke.md @@ -33,11 +33,11 @@ Invokes a `proxy` with a specified dispatch type, an overload type, and argument - `(1)` Let `ptr` be the contained value of the `proxy` object associated to `p` with the same cv ref-qualifiers. Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), *ptr, static_cast(args)...)`. - `(2)` Let `ptr` be the contained value of `p` with the same cv ref-qualifiers. Equivalent to [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D(), ptr, static_cast(args)...)`. The behavior is undefined if `p` does not contain a value. -There shall be a convention type `Conv` defined in `typename F::convention_types` where +There shall be a convention type `Conv` defined in the convention types of `F` or of any super of `F`, reachable via `typename F::super_types` transitively, where - `Conv::is_direct` is `false` (for `(1)`) or `true` (for `(2)`), and - `typename Conv::dispatch_type` is `D`, and -- there shall be an overload type `O1` defined in `typename Conv::overload_types` where [`substituted-overload`](ProOverload.md)`` is `O`. +- [`substituted-overload`](ProOverload.md)`` is `O`. ## Notes diff --git a/docs/spec/proxy_view.md b/docs/spec/proxy_view.md index 2f81c5d3..15aa6563 100644 --- a/docs/spec/proxy_view.md +++ b/docs/spec/proxy_view.md @@ -15,14 +15,15 @@ using proxy_view = proxy>; `proxy_view` is a non-owning, trivially copyable, trivially relocatable view of an object that models [`proxiable_target`](proxiable_target.md). It behaves like a `proxy` except that it never owns the lifetime of the underlying object. -`observer_facade` adapts an existing [facade](facade.md) `F` for this non-owning use. The adaptation preserves only those parts of `F` that remain semantically valid when the storage is reduced to a single pointer and modifies substitution conversions so that view-ness is preserved (substitution that would have produced an owning `proxy` instead produces a `proxy_view`). +`observer_facade` adapts an existing [facade](facade.md) `F` for this non-owning use. The adaptation preserves only those parts of `F` that remain semantically valid when the storage is reduced to a single pointer. Each super of `F` is adapted in the same way, so that view-ness is preserved when converting to a `proxy` of a super: a `proxy_view` converts to a `proxy_view` for every super `G` of `F`. ## Member Types of `observer_facade` -| Name | Description | -| ------------------ | ------------------------------------------------------------ | -| `convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type transformed from `typename F::convention_types`. Specifically, for each convention `C` in `typename F::convention_types`:
- If `C::is_direct` is `false`, include `C` unchanged.
- Otherwise, if `typename C::dispatch_type` is [`substitution_dispatch`](./substitution_dispatch/README.md), include a transformed convention `C'` whose
* `is_direct` is `true` and `dispatch_type` is still `substitution_dispatch`.
* For every overload `O` in `typename C::overload_types` with signature (after cv/ref/noexcept qualifiers) returning a `proxy`, replace its return type with `proxy_view` while preserving qualifiers and `noexcept`.
- Otherwise `C` is discarded. | -| `reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type transformed from `typename F::reflection_types`. Specifically, for each reflection type `R` in `typename F::reflection_types`, `R` is included when `R::is_direct` is `false`, or otherwise discarded. | +| Name | Description | +| ---------------------------------- | ------------------------------------------------------------ | +| `super_types`
*(since 5.0.0)* | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type transformed from `typename F::super_types`. Specifically, for each super `G` in `typename F::super_types`, `observer_facade` is included. | +| `convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type transformed from `typename F::convention_types`. Specifically, for each convention `C` in `typename F::convention_types`:
- If `C::is_direct` is `false`, include `C` unchanged.
- Otherwise, if `typename C::dispatch_type` is [`substitution_dispatch`](./substitution_dispatch/README.md), include a transformed convention `C'` whose `is_direct` is `true`, `dispatch_type` is still `substitution_dispatch`, and whose `overload_type` is `typename C::overload_type` with a return type of `proxy` replaced by `proxy_view` and qualifiers replaced by `const noexcept`.
- Otherwise `C` is discarded. Duplicates are removed. | +| `reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type transformed from `typename F::reflection_types`. Specifically, for each reflection type `R` in `typename F::reflection_types`, `R` is included when `R::is_direct` is `false`, or otherwise discarded. | ## Member Constants of `observer_facade` diff --git a/docs/spec/weak_proxy.md b/docs/spec/weak_proxy.md index 64456e7e..0c71ce39 100644 --- a/docs/spec/weak_proxy.md +++ b/docs/spec/weak_proxy.md @@ -18,15 +18,16 @@ using weak_proxy = proxy>; `weak_facade` adapts the original [facade](facade.md) `F` so that: * A `lock()` member (direct convention) is provided, returning a `proxy` that contains a value if and only if the referenced object is still alive at the time of the call. -* All direct substitution conversions that would have produced a `proxy` become conversions that produce a `weak_proxy` instead (so that "weak-ness" is preserved across facade-substitution). +* Each super of `F` is adapted in the same way, so that "weak-ness" is preserved when converting to a `proxy` of a super: a `weak_proxy` converts to a `weak_proxy` for every super `G` of `F`. * No reflections from `F` are preserved. ## Member Types of `weak_facade` -| Name | Description | -| ---- | ----------- | -| `convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type transformed from `typename F::convention_types`. Specifically:
- It always prepends a direct convention whose dispatch type denotes the member function `lock` and whose single overload has signature `proxy() const noexcept`. Calling this overload attempts to obtain a strong `proxy`; it returns an empty `proxy` if the object has expired.
- For any direct convention `C` in `F` whose `dispatch_type` is `substitution_dispatch`, a transformed convention `C'` is included, whose
* `is_direct` is `true` and `dispatch_type` is still `substitution_dispatch`.
* For every overload `O` in `typename C::overload_types` with signature (after cv/ref/noexcept qualifiers) returning a `proxy`, replace its return type with `weak_proxy` while preserving qualifiers and `noexcept`.
- All other conventions from `F` are discarded. | -| `reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains no types. | +| Name | Description | +| ---------------------------------- | ----------- | +| `super_types`
*(since 5.0.0)* | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type transformed from `typename F::super_types`. Specifically, for each super `S` in `typename F::super_types`, `weak_facade` is included. | +| `convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that always contains a direct convention whose dispatch type denotes the member function `lock` and whose overload has signature `proxy() const noexcept`. Calling this overload attempts to obtain a strong `proxy`; it returns an empty `proxy` if the object has expired. For each direct convention `C` in `typename F::convention_types` whose `dispatch_type` is [`substitution_dispatch`](./substitution_dispatch/README.md), a transformed convention `C'` is also included, whose `is_direct` is `true`, `dispatch_type` is still `substitution_dispatch`, and whose `overload_type` is `typename C::overload_type` with a return type of `proxy` replaced by `weak_proxy`, preserving qualifiers. All other conventions from `F` are discarded. | +| `reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains no types. | ## Member Constants of `weak_facade` diff --git a/include/proxy/v4/detail/core.h b/include/proxy/v4/detail/core.h index 4262904b..897cb632 100644 --- a/include/proxy/v4/detail/core.h +++ b/include/proxy/v4/detail/core.h @@ -39,9 +39,8 @@ namespace detail { template struct basic_facade_traits; - template -struct proxy_meta; +struct facade_traits; } // namespace detail @@ -95,6 +94,13 @@ struct specialization_type_traits, Args...> template