From 1ebe71f1913bde9556b3974745982d9ba688d3ef Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Thu, 11 Jun 2026 13:32:26 +0200 Subject: [PATCH 1/2] Edits after discussion with Tony van Eerd --- DRAFT.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/DRAFT.md b/DRAFT.md index 6eecab5..feea1d4 100644 --- a/DRAFT.md +++ b/DRAFT.md @@ -6,7 +6,7 @@ P4148R2 Working Group: Library Evolution, Library -Date: 2026-06-07 +Date: 2026-06-11 _Jonathan Coe \<\>_ @@ -46,6 +46,7 @@ and code injection and focuses solely on the design of the class templates ### Changes in revision R2 - Support zero-cost conversion from a compatible `protocol` or `protocol_view` to a narrower target interface (subtype substitution). +- Add `any` to the standard library types equivalence table. ### Changes in revision R1 @@ -366,6 +367,17 @@ existing set of function-objects. Consider the structural types below: +```c++ +struct Any {}; +``` + +```c++ +struct MoveOnlyAny { + MoveOnlyAny(const MoveOnlyAny&) = delete; + MoveOnlyAny& operator=(const MoveOnlyAny&) = delete; +}; +``` + ```c++ template struct Function { @@ -427,6 +439,8 @@ overload set. The table below is illustrative of how flexible `protocol` and | Standard library type | Protocol equivalent | | :------------------------------------------ | :----------------------------------------------- | +| `any` | `protocol` | +| ??? |`protocol` | | `copyable_function` | `protocol>` | | `move_only_function` | `protocol>` | | `function_ref` | `protocol_view>` | @@ -489,7 +503,6 @@ The table below summarises the main design choices side by side. | Interface definition | C++ struct | `facade_builder` + dispatch objects (explicit) | | Interaction syntax | `p.draw()` | `p->draw()` | | Layout constraints | Implementation defined | Encoded in the Facade type | -| Subtype substitution | Supported | Implicit via `add_facade` | | Ownership model | Explicit | Erased | ### Design Alternatives @@ -550,6 +563,9 @@ properties required by this proposal. ## Acknowledgements +The authors would like to thank Billy Baker, Tony van Eerd and the BSI C++ +Panel for suggestions and useful discussion. + ## References [PEP 544] _Protocols: Structural subtyping (static duck typing)_. From a60979f58836b9c4a12f38dfeddbb518768e93b2 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Thu, 11 Jun 2026 17:17:20 +0200 Subject: [PATCH 2/2] Fix typos --- DRAFT.md | 66 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/DRAFT.md b/DRAFT.md index feea1d4..96a7d0b 100644 --- a/DRAFT.md +++ b/DRAFT.md @@ -89,10 +89,10 @@ and leading to inconsistent semantics across libraries. This situation can be understood in terms of the broader polymorphism design space: -| | Static | Dynamic | -|-------------------|:------------:|:--------------:| -| Nominal typing | Templates | Virtual | -| Structural typing | Concepts | --- | +| | Static | Dynamic | +| ----------------- | :-------: | :-----: | +| Nominal typing | Templates | Virtual | +| Structural typing | Concepts | --- | The absence of a language-supported mechanism for dynamic structural typing explains the proliferation of type-erasure-based abstractions. Each such abstraction can be @@ -103,10 +103,10 @@ Protocols unify and generalise existing type-erasure patterns, providing a consi non-intrusive mechanism for expressing dynamic structural polymorphism, while also providing consistent support for allocators: -| | Static | Dynamic | -|-------------------|:------------:|:--------------:| -| Nominal typing | Templates | Virtual | -| Structural typing | Concepts | Protocol | +| | Static | Dynamic | +| ----------------- | :-------: | :------: | +| Nominal typing | Templates | Virtual | +| Structural typing | Concepts | Protocol | ## Design @@ -159,6 +159,7 @@ move assignment (and allocator-extended equivalents) are generated unconditional ```c++ template class protocol> { + public: // Default constructor. explicit constexpr protocol(); // conditionally-generated @@ -245,6 +246,8 @@ class protocol> { ```c++ template <> class protocol_view { + public: + // Constructor from any mutable conforming object. template constexpr protocol_view(T& obj) noexcept; @@ -290,6 +293,8 @@ class protocol_view { ```c++ template <> class protocol_view { + public: + // Constructor from any const conforming object. template constexpr protocol_view(const T& obj) noexcept; @@ -368,13 +373,20 @@ existing set of function-objects. Consider the structural types below: ```c++ -struct Any {}; +struct Any { + // All special member functions are defaulted. +}; ``` ```c++ struct MoveOnlyAny { + // Deleted copy constructor and copy assignment. MoveOnlyAny(const MoveOnlyAny&) = delete; MoveOnlyAny& operator=(const MoveOnlyAny&) = delete; + + // Defaulted move constructor and move assignment. + MoveOnlyAny(MoveOnlyAny&&) = default; + MoveOnlyAny& operator=(MoveOnlyAny&&) = default; }; ``` @@ -437,18 +449,18 @@ There is currently no function-type in the standard library that can represent a overload set. The table below is illustrative of how flexible `protocol` and `protocol_view` are: -| Standard library type | Protocol equivalent | -| :------------------------------------------ | :----------------------------------------------- | -| `any` | `protocol` | -| ??? |`protocol` | -| `copyable_function` | `protocol>` | -| `move_only_function` | `protocol>` | -| `function_ref` | `protocol_view>` | -| `copyable_function` | `protocol>` | -| `move_only_function` | `protocol>` | -| `function_ref` | `protocol_view>` | -| ??? | `protocol` | -| ??? | `protocol_view` | +| Standard library type | Protocol equivalent | +| :------------------------------------- | :----------------------------------------------- | +| `any` | `protocol` | +| ??? | `protocol` | +| `copyable_function` | `protocol>` | +| `move_only_function` | `protocol>` | +| `function_ref` | `protocol_view>` | +| `copyable_function` | `protocol>` | +| `move_only_function` | `protocol>` | +| `function_ref` | `protocol_view>` | +| ??? | `protocol` | +| ??? | `protocol_view` | ### Comparison with proxy @@ -498,12 +510,12 @@ object is determined by the choice of pointer, not by `proxy`. The table below summarises the main design choices side by side. -| Aspect | `protocol` | `proxy` | -| :--- | :--- | :--- | -| Interface definition | C++ struct | `facade_builder` + dispatch objects (explicit) | -| Interaction syntax | `p.draw()` | `p->draw()` | -| Layout constraints | Implementation defined | Encoded in the Facade type | -| Ownership model | Explicit | Erased | +| Aspect | `protocol` | `proxy` | +| :------------------- | :--------------------- | :--------------------------------------------- | +| Interface definition | C++ struct | `facade_builder` + dispatch objects (explicit) | +| Interaction syntax | `p.draw()` | `p->draw()` | +| Layout constraints | Implementation defined | Encoded in the Facade type | +| Ownership model | Explicit | Erased | ### Design Alternatives