diff --git a/DRAFT.md b/DRAFT.md index 41efdd0..548efec 100644 --- a/DRAFT.md +++ b/DRAFT.md @@ -238,8 +238,543 @@ header ``." ## Technical Specifications -TODO(jbcoe): Adopt relevant wording from value-types, add wording for reflected -methods. +## Header `` synopsis [version.syn] + +Note to editors: Add the following macro with editor provided values to +[version.syn] + +```cpp +#define __cpp_lib_protocol ??????L +``` + +### Header `` synopsis [protocol.syn] + +```cpp +namespace std { + + // [protocol], class template protocol + template> + class protocol; + + // [protocol_view], class template protocol_view + template + class protocol_view; + + namespace pmr { + template using protocol = + std::protocol>; + + template using protocol_view = + std::protocol_view; + } +} +``` + +### X.Y Class template protocol [protocol] + +[Drafting note: The member _`alloc`_ and _`vtable`_ should be formatted as exposition only identifiers, +but limitations of the processor used to prepare this paper means not all uses are italicised.] + +#### X.Y.1 Class template protocol general [protocol.general] + +1. A `protocol` object manages the lifetime of an owned object that erases the type of a conforming +implementation. A `protocol` object is _valueless_ if it has no owned object. A `protocol` object may +become valueless only after it has been moved from. + +2. An object of type `T` _conforms to an interface_ `I` if all member functions declared in `I` are +available on `T` with matching signatures and are not deleted. Const-qualifiers in the interface's +member functions are required to match. + +3. In every specialization `protocol`, if the type `allocator_traits::value_type` +is not the same type as `I`, the program is ill-formed. Every object of type `protocol` +uses an object of type `Allocator` to allocate and free storage for the owned object as needed. + +4. The member `alloc` is used for any memory allocation and element construction performed by member +functions during the lifetime of each `protocol` object. The allocator `alloc` may be replaced only by +assignment or `swap()`. Allocator replacement is performed by copy assignment, move assignment, or swapping +of the allocator only if ([container.reqmts]): + `allocator_traits::propagate_on_container_copy_assignment::value`, or\ + `allocator_traits::propagate_on_container_move_assignment::value`, or\ + `allocator_traits::propagate_on_container_swap::value` +is `true` within the implementation of the corresponding `protocol` operation. + +5. A program that instantiates the definition of the template `protocol` with a type for the +`I` parameter that is a non-object type, an array type, or a cv-qualified type is ill-formed. + +6. The template parameter `I` of `protocol` shall be a complete type. The program is ill-formed if a +type instantiates `protocol` with an incomplete type `I`. + +7. The template parameter `Allocator` of `protocol` shall meet the +_Cpp17Allocator_ requirements. + +8. If a program declares an explicit or partial specialization of `protocol`, the behavior is undefined. + +## Header `` synopsis [version.syn] + +Note to editors: Add the following macros with editor provided values to +[version.syn] + +```cpp +#define __cpp_lib_protocol ??????L +``` + +#### X.Y.2 Class template protocol synopsis [protocol.syn] + +```cpp +template > +class protocol { + public: + using interface_type = I; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + + constexpr protocol(const protocol& other); + + constexpr protocol(allocator_arg_t, const Allocator& a, + const protocol& other); + + constexpr protocol(protocol&& other) noexcept; + + constexpr protocol(allocator_arg_t, const Allocator& a, + protocol&& other) noexcept(see below); + + template + explicit constexpr protocol(in_place_type_t); + + template + explicit constexpr protocol(allocator_arg_t, const Allocator& a, + in_place_type_t); + + template + explicit constexpr protocol(in_place_type_t, Us&&... us); + + template + explicit constexpr protocol(allocator_arg_t, const Allocator& a, + in_place_type_t, Us&&... us); + + ~protocol(); + + constexpr protocol& operator=(const protocol& other); + + constexpr protocol& operator=(protocol&& other) noexcept(see below); + + constexpr allocator_type get_allocator() const noexcept; + + constexpr bool valueless_after_move() const noexcept; + + constexpr void swap(protocol& other) noexcept(see below); + + //constexpr void swap(protocol& lhs, protocol& rhs) noexcept(noexcept(lhs.swap(rhs))); + + private: + Allocator alloc = Allocator(); // exposition only +}; +``` + +#### X.Y.3 Constructors [protocol.ctor] + +The following element applies to all functions in [protocol.ctor]: + +_Throws_: Nothing unless `allocator_traits::allocate` or +`allocator_traits::construct` throws. + +```cpp +constexpr protocol(const protocol& other); +``` + +3. _Effects_: `alloc` is direct-non-list-initialized with\ +`allocator_traits::select_on_container_copy_construction(other.alloc)`. +If `other` is valueless, `*this` is valueless. Otherwise, constructs an owned object +of the same type as the owned object in `other`, with the object owned in `other` +using the allocator `alloc`. + +```cpp +constexpr protocol(allocator_arg_t, const Allocator& a, + const protocol& other); +``` + +4. _Effects_: `alloc` is direct-non-list-initialized with `a`. If `other` is +valueless, `*this` is valueless. Otherwise, constructs an owned object of the same +type as the owned object in `other`, with the object owned in `other` using +the allocator `alloc`. + +```cpp +constexpr protocol(protocol&& other) noexcept; +``` + +5. _Effects_: `alloc` is direct-non-list-initialized from `std::move(other.alloc)`. +If `other` is valueless, `*this` is valueless. Otherwise `*this` takes +ownership of the owned object of `other`, or owns an object of the same type +constructed from the owned object of `other` considering that owned object +as an rvalue, using the allocator `alloc`. + +```cpp +constexpr protocol(allocator_arg_t, const Allocator& a, protocol&& other) + noexcept(allocator_traits::is_always_equal::value); +``` + +6. _Effects_: `alloc` is direct-non-list-initialized with `a`. If `other` is +valueless, `*this` is valueless. Otherwise, if `alloc == other.alloc` is `true`, +either constructs an object of type `protocol` that owns the owned object of other, +making `other` valueless; or, owns an object of the same type constructed from the +owned object of `other` considering that owned object as an rvalue. Otherwise, if +`alloc != other.alloc` is `true`, constructs an owned object of the same type +as the owned object in `other`, with the owned object in `other` as an rvalue, +using the allocator `alloc`. + +```cpp +template +explicit constexpr protocol(in_place_type_t); +``` + +7. _Constraints_: + * `is_default_constructible_v` is `true`, and + * `T` conforms to interface `I`. + +8. _Effects_: Constructs an owned object of type `T` with an empty argument list +using the allocator `alloc`. + +```cpp +template +explicit constexpr protocol(allocator_arg_t, const Allocator& a, + in_place_type_t); +``` + +9. _Constraints_: + * `is_default_constructible_v` is `true`, and + * `T` conforms to interface `I`. + +10. _Effects_: `alloc` is direct-non-list-initialized with `a`. Constructs an +owned object of type `T` with an empty argument list using the allocator `alloc`. + +```cpp +template +explicit constexpr protocol(in_place_type_t, Us&&... us); +``` + +11. _Constraints_: + * `is_same_v, T>` is `true`, + * `is_constructible_v` is `true`, + * `T` conforms to interface `I`, and + * `is_default_constructible_v` is `true`. + +12. _Effects_: Constructs an owned object of type `T` with `std::forward(us)...` +using the allocator `alloc`. + +```cpp +template +explicit constexpr protocol(allocator_arg_t, const Allocator& a, + in_place_type_t, Us&&... us); +``` + +13. _Constraints_: + * `is_same_v, T>` is `true`, + * `is_constructible_v` is `true`, and + * `T` conforms to interface `I`. + +14. _Effects_: `alloc` is direct-non-list-initialized with `a`. Constructs an +owned object of type `T` with `std::forward(us)...` using the allocator +`alloc`. + +#### X.Y.4 Destruction [protocol.dtor] + +```cpp +~protocol(); +``` + +1. _Effects_: If `*this` is not valueless, calls `allocator_traits::destroy(p)`, +where `p` is a pointer of type `U*` to the owned object and `U` is the type of the owned object; +then the storage is deallocated. + + +#### X.Y.5 Assignment [protocol.assign] + +```cpp +constexpr protocol& operator=(const protocol& other); +``` + +1. _Mandates_: `T` is a complete type. + +2. _Effects_: If `addressof(other) == this` is `true`, there are no effects. Otherwise: + +Changes `*this` to a deep copy of the owned object of `other`. If +`other` is valueless, `*this` is valueless after assignment. If an exception is +thrown, `*this` is unchanged. If `*this` already contains an owned object and +`alloc == other.alloc`, the assignment is performed in-place where possible; +otherwise the old owned object is destroyed and a new one is created. + + 2.1. The allocator needs updating if\ + `allocator_traits::propagate_on_container_copy_assignment::value`\ + is `true`. + + 2.2. If `other` is not valueless, a new owned object of type `U`, where `U` is the type of + the owned object in `other`, is constructed in `*this` using `allocator_traits::construct` + with the owned object from `other` as the argument, using either the allocator in `*this` + or the allocator in `other` if the allocator needs updating. + + 2.3 The previously owned object in `*this`, if any, is destroyed using `allocator_traits::destroy` + and then the storage is deallocated. + + 2.4 If the allocator needs updating, the allocator in `*this` is replaced with a copy of the allocator in + `other`. + +3. _Returns_: `*this`. + +4. _Remarks_: If any exception is thrown, there are no effects on `*this`. + +```cpp +protocol& operator=(protocol&& other) noexcept( + allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); +``` + +5. _Mandates_: If `allocator_traits​::​propagate_on_container_move_assignment​::​value` is `false` +and `allocator_traits​::​is_always_equal​::​value` is `false`, `I` is a complete type. + +6. _Effects_: If `addressof(other) == this` is `true`, there are no effects. Otherwise: + + 6.1. The allocator needs updating if\ + `allocator_traits::propagate_on_container_move_assignment::value`\ + is `true`. + + 6.2. If `other` is valueless, `*this` becomes valueless. + + 6.3 Otherwise, if the allocator needs updating or `alloc == other.alloc` is `true`, `*this` + takes ownership of the owned object of `other`. + + 6.4 Otherwise, constructs a new owned object of type `U`, where `U` is the type of the owned object in `other`, + with the owned object of `other` as the argument as an rvalue, using the allocator in `*this`. + + 6.4. The previously owned object in `*this`, if any, is destroyed using `allocator_traits::destroy` + and then the storage is deallocated. + + 6.5. If the allocator needs updating, the allocator in `*this` is replaced with a copy of the + allocator in `other`. + +7. _Returns_: A reference to `*this`. + +8. _Remarks_: If any exception is thrown, there are no effects on `*this` or `other`. + +#### X.Y.6 Valued state queries [protocol.observers] + +```cpp +constexpr bool valueless_after_move() const noexcept; +``` + +1. _Returns_: `true` if `*this` is valueless after a move, otherwise `false`. + +```c++ +constexpr allocator_type get_allocator() const noexcept; +``` + +2. _Returns_: `alloc`. + +#### X.Y.7 Swap [protocol.swap] + +```cpp +constexpr void swap(protocol& other) noexcept( + allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); +``` + +1. _Preconditions_: If `allocator_traits​::​propagate_on_container_swap​::​value` is `true`, +then `Allocator` meets the _Cpp17Swappable_ requirements. Otherwise `get_allocator() == other`. +`get_allocator()` is `true`. + +2. _Effects_: Swaps the states of `*this` and `other`, exchanging owned objects or valueless states. +If `allocator_traits​::​propagate_on_container_swap​::​value` is true, then the allocators of +`*this` and `other` are exchanged by calling swap as described in [swappable.requirements]. Otherwise, +the allocators are not swapped. + +[Note 1: Does not call swap on the owned objects directly. — end note] + +3. _Remarks_: This function is a no-op if both arguments are valueless before the call. + + + + + +### X.Z Class template protocol_view [protocol_view] + +#### X.Z.1 Class template protocol_view general [protocol_view.general] + +1. A `protocol_view` object provides a non-owning reference to an object that conforms to an +interface `I`. Copying a `protocol_view` produces a new view referring to the same object. + +2. An object of type `T` _conforms to an interface_ `I` if all member functions declared in `I` are +available on `T` with matching signatures and are not deleted. Const-qualifiers in the interface's +member functions are required to match. + +3. A program that instantiates the definition of the template `protocol_view` +with a type for the `I` parameter that is a non-object type, an array type, or a cv-qualified type is ill-formed. + +4. The template parameter `I` of `protocol_view` shall be a complete type. The program is ill-formed if a +type instantiates `protocol_view` with an incomplete type `I`. + +5. If a program declares an explicit or partial specialization of `protocol_view`, +the behavior is undefined. + +#### X.Z.2 Class template protocol_view synopsis [protocol_view.syn] + +```cpp +template +class protocol_view { + public: + using interface_type = I; + + template + constexpr protocol_view(T& t) noexcept; + + template + constexpr protocol_view(const T& t) noexcept; + + template + constexpr protocol_view(protocol& p) noexcept; + + template + constexpr protocol_view(const protocol& p) noexcept; + + template + constexpr protocol_view(protocol_view& view) noexcept; + + template + constexpr protocol_view(const protocol_view& view) noexcept; + + constexpr protocol_view(const protocol_view&) noexcept = default; + + constexpr protocol_view(protocol_view&&) noexcept = default; + + constexpr protocol_view& operator=(const protocol_view&) noexcept = default; + + private: + I* data_; // exposition only +}; +``` + +#### X.Z.3 Constructors [protocol_view.ctor] + +```cpp +template +constexpr protocol_view(T& t) noexcept; +``` + +1. _Constraints_: `T` conforms to interface `I`. + +2. _Preconditions_: `t` shall refer to an object that is valid and remains valid for the lifetime of `*this`. + +3. _Effects_: Initializes `data_` to `std::addressof(t)`. + +```cpp +template +constexpr protocol_view(const T& t) noexcept; +``` + +4. _Constraints_: `T` conforms to interface `I` and `is_const_v` is `true`. + +5. _Preconditions_: `t` shall refer to an object that is valid and remains valid for the lifetime of `*this`. + +6. _Effects_: Initializes `data_` with the address of `t`. + +```cpp +template +constexpr protocol_view(protocol& p) noexcept; +``` + +7. _Preconditions_: protocol `p` is not valueless. + +8. _Effects_: Initializes `data_` to `std::addressof(*p)`. + +```cpp +template +constexpr protocol_view(const protocol& p) noexcept; +``` +9. _Constraints_: `is_const_v` is `true`. + +10. _Preconditions_: protocol `p` is not valueless. + +11. _Effects_: Initializes `data_` with the address of `*p`. + +```cpp +template +constexpr protocol_view(protocol_view& view) noexcept; +``` + +12. _Constraints_: `const U` is implicitly convertible to `const I` (allowing different `const`-qualifications of the same interface). + +13. _Preconditions_: The object referenced by `view` does not become invalid before use of `*this`. + +14. _Effects_: Initializes `data_` with the address of the object referenced by `view`. + +```cpp +template +constexpr protocol_view(const protocol_view& view) noexcept; +``` + +15. _Constraints_: `const U` is implicitly convertible to `const I` and `is_const_v` is `true`. + +16. _Preconditions_: The object referenced by `view` does not become invalid before use of `*this`. + +17. _Effects_: Initializes `data_` with the address of the object referenced by `view`. + + +```cpp +constexpr protocol_view(const protocol_view& other) noexcept = default; +``` + +18. _Effects_: Initializes `data_` with the values from `other`. + +```cpp +constexpr protocol_view(protocol_view&& other) noexcept = default; +``` + +19. _Effects_: Initializes `data_` with values from `other`. + +#### X.Z.4 Assignment [protocol_view.assign] + +```cpp +constexpr protocol_view& operator=(const protocol_view& other) noexcept = default; +``` + +1. _Effects_: Assigns `data_` from `other`. + +2. _Returns_: `*this`. + +```cpp +constexpr protocol_view& operator=(protocol_view&& other) noexcept = default; +``` + +3. _Effects_: Assigns `data_` from `other`. + +4. _Returns_: `*this`. + +#### X.Z.4 Member access + +TODO:ADD ? ## Polls @@ -273,3 +808,8 @@ properties required by this proposal. [py_cppmodel] _Python wrappers for clang's parsing of C++ to simplify AST analysis_. + +.html> + +[py_cppmodel] _Python wrappers for clang's parsing of C++ to simplify AST +analysis_.