ISO/IEC JTC 1/SC 22/WG 21 P2081R1
Date: 2020-02-14
Audience: LEWG, LWG
Thomas Köppe <tkoeppe@google.com>The Library Fundamentals v3 TS should be based on C++20.
make_array
(with discussion);
provide full edit instructions for Mandates/... changes, and use the new
“enabled hash specialization” wording.The working draft of the Extensions for Library Fundamentals, Version 3 Technical Specification (“LFTSv3” or just “LFTS” for short) is currently (as of P0996R1) based on the published C++ standard, i.e. C++17. It is very unlikely, and indeed not planned at this point, that we will publish the TS before the C++20 DIS has been published (which we expect to happen at the next meeting as of the time of writing, which is Prague 2020). Therefore, we have the option of basing the TS on the C++20 DIS, and we should do this to allow us to remove facilities that have been merged into the main standard, and to take advantage of new language facilities.
If the C++20 IS is published before we complete the PDTS ballot for the LFTS, we should update the LFTS working draft to refer to the IS instead of the DIS. The acceptance of this proposal should include approval of such a future change, which would then be an editorial matter to align the wording with the design intent.
A noteworthy removal: We propose to remove make_array
from the TS. The feature was added to the TS by
N4391
(adopted in Lenexa 2015) together with to_array
. Later,
P0325R4
(adopted in Cologne 2019) added to_array
to the C++20 working draft,
but explained
that because of class template argument deduction, “we no longer need make_array
”.
Other removals: Uniform container erasure was moved into C++20 by
P1209R0
(adopted in San Diego 2018), and source_location
was moved by
P1208R6
(adopted in Cologne 2019).
Modify [1.2, general.references] paragraphs 1, 2, and 3 as follows:
1.2 Normative references [general.references]
1. The following referenced document is indispensable for the application of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.
[Note: Under preparation. Stage at the time of publication: ISO/DIS 14882:2020. — end note]
2. ISO/IEC 14882:201714882:– is herein
called the C++ Standard. References to clauses within the C++
Standard are written as "C++17C++20 §3.2". The
library described in ISO/IEC 14882:2017 clauses
20–3314882:– clauses 16–32 is herein
called the C++ Standard Library.
3. Unless otherwise specified, the whole of the C++ Standard's Library
introduction (C++17 §20C++20 §16) is included into
this Technical Specification by reference.
Modify [1.3, general.namespaces] paragraphs 2:
2. Each header described in this technical specification shall import the
contents of std::experimental::fundamentals_v3
into
std::experimental
as if by
Delete subclause [6, container]. This includes the deletion of make_array
,
as discussed above, which does not appear in C++20.
6 Containers [container]
6.1 Uniform container erasure [container.erasure]
6.1.1 Header synopsis [container.erasure.syn]
1. For brevity, […]
[…] are intentionally not provided. – end note]
6.2 Class template array
[container.array]
6.2.1 Header <experimental/array>
synopsis [array.syn]
[…]
6.2.2 Array creartion functions [container.array.creation]
[…]
Delete clause [11, reflection].
11 Reflection library [reflection]
[…]
Delete from Table 1 — C++ library headers:
<experimental/algorithm>
<experimental/array>
<experimental/deque>
<experimental/forward_list>
<experimental/functional>
<experimental/future>
<experimental/iterator>
<experimental/list>
<experimental/map>
<experimental/memory>
<experimental/memory_resource>
<experimental/propagate_const>
<experimental/random>
<experimental/scope>
<experimental/set>
<experimental/source_location>
<experimental/string>
<experimental/type_traits>
<experimental/unordered_map>
<experimental/unordered_set>
<experimental/utility>
<experimental/vector>
Delete from Table 2 — Significant features in this technical specification:
Doc. No. | Title | […] |
---|---|---|
N4388 | A Proposal to Add a Const-Propagating Wrapper to the Standard Library | […] |
[…] | […] | […] |
make_array |
||
[…] | […] | […] |
Editorially apply the new compact inline namespace syntax wherever it applies.
3.1.1 Header <experimental/utility> synopsis [utility.syn]
[Further edits not shown.]
Update section numbers, and update the “C++17-concept” names everywhere
and replace “satisfies” with “meets”, e.g. “satisfies
the requirements of CopyConstructible
” becomes “meets
the Cpp17CopyConstructible requirements”.
20.7.720.10.8 uses_allocator [allocator.uses]
20.7.7.120.10.8.1 uses_allocator trait [allocator.uses.trait]
template <class T, class Alloc> struct uses_allocator;
1. Remarks: Automatically detects whether T
has a nested
allocator_type
that is convertible from Alloc
.
Meets the BinaryTypeTraitCpp17BinaryTypeTrait
requirements (C++17 §23.15.1C++20 §20.15.1).
The implementation shall provideprovides a definition […]
[Further edits not shown, though some instances will be part of the edits of the next instruction.]
Update C++17-style Requires/Remarks into Mandates/Expects/Constraints.
3.2.2.3 propagate_const
constructors [propagate_const.ctor]
[Note: The following constructors are conditionally specified as explicit
.
This is typically implemented by declaring two such constructors, of which at most
one participates in overload resolution. — end note]
template <class U> see below constexpr propagate_const(propagate_const<U>&& pu);
Constraints: is_constructible_v<T, U>
is true
.
Remarks:
This constructor shall not participate in overload resolution unless
The constructor is specified as explicit if and only if is_constructible_v<T, U&&>
.!is_convertible_v<U&&, T>
.
Effects: Initializes t_
as if direct-non-list-initializing an object of type
T
with the expression std::move(pu.t_)
.
template <class U> see below constexpr propagate_const(U&& pu);
Constraints: is_constructible_v<T, U>
is true
and
decay_t<U>
is not a specialization of propagate_const
.
Remarks:
This constructor shall not participate in overload resolution unless
The constructor is specified as explicit if and only if is_constructible_v<T, U&&>
and decay_t<U>
is not a specialization of propagate_const
.!is_convertible_v<U&&, T>
.
Effects: Initializes t_
as if direct-non-list-initializing an object of type
T
with the expression std::forward<U>(u)
.
Editorial note: The rvalue reference in is_constructible
is redundant,
since it is already contained in the definition of is_constructible
(or, more concretely,
in the definition of declval
), and therefore we remove it here.
3.2.2.4 propagate_const
assignment [propagate_const.assignment]
[…]
Remarks: This function shall not participate in overload resolution unlessConstraints:
U
is implicitly convertible to T
.
[…]
Remarks: This function shall not participate in overload resolution unlessConstraints:
U
is implicitly convertible to T
and decay_t<U>
is not a specialization of propagate_const
.
[…]
3.2.2.5 propagate_const
const observers [propagate_const.const_observers]
[…]
Remarks: This function shall not participate in overload resolution unlessConstraints:
T
is an object pointer type or has an implicit conversion to const element_type*
.
[…]
3.2.2.6 propagate_const
non-const observers [propagate_const.non_const_observers]
[…]
Remarks: This function shall not participate in overload resolution unlessConstraints:
T
is an object pointer type or has an implicit conversion to const element_type*
.
[…]
3.2.2.11 propagate_const
hash support [propagate_const.hash]
The specialization hash<experimental::fundamentals_v3::propagate_const<T>>
is enabled (C++20 §20.14.18) if and only if hash<T>
is enabled.
ForWhen enabled, for an object p
of type propagate_const<T>
,
hash<experimental::fundamentals_v3::propagate_const<T>>()(p)
shall evaluateevaluates to the same value as hash<T>()(p.t_)
.
Requires: The specialization
hash<T>
shall be well-formed and well-defined, and shall meet the requirements of class template hash
.
3.2.2.12 propagate_const
comparison function objects [propagate_const.comparison_function_objects]
[…]
RequiresMandates: The specialization
equal_to<T>
shall beis well-formed.
Preconditions: The specialization
equal_to<T>
is and well-defined.
[…]
RequiresMandates: The specialization
not_equal_to<T>
shall beis well-formed.
Preconditions: The specialization
not_equal_to<T>
is and well-defined.
[…]
RequiresMandates: The specialization
less<T>
shall beis well-formed.
Preconditions: The specialization
less<T>
is and well-defined.
[…]
RequiresMandates: The specialization
greater<T>
shall beis well-formed.
Preconditions: The specialization
greater<T>
is and well-defined.
[…]
RequiresMandates: The specialization
less_equal<T>
shall beis well-formed.
Preconditions: The specialization
less_equal<T>
is and well-defined.
[…]
RequiresMandates: The specialization
greater_equal<T>
shall beis well-formed.
Preconditions: The specialization
greater_equal<T>
is and well-defined.
[…]
Class templates scope_exit
, scope_fail
, and scope_success
[scopeguard.exit]
[…]
RequiresMandates:
The expression f()
shall beis well-formed.
Preconditions:
Calling f()
shall havehas well-defined behavior.
For scope_exit
and scope_fail
, calling f()
shalldoes not throw an exception.
Effects:
If EFP
is not an lvalue reference type and
is_nothrow_constructible_v<EF, EFP>
is true
,
initialize exit_function
with std::forward<EFP>(f)
;
otherwise initialize exit_function
with f
.
For scope_exit
and scope_fail
,
if the initialization of exit_function
throws an exception,
calls f()
. [Note: For scope_success
,
f()
will not be called if the initialization fails. — end note]
Throws: Any exception thrown during the initialization of exit_function
.
Remarks: This constructor shall not participate in overload resolution unless
Constraints: is_same_v<remove_cvref_t<EFP>, scope-guard>
is false
and is_constructible_v<EF, EFP>
is true
.
RequiresPreconditions: If EF
is an object type:
is_nothrow_move_constructible_v<EF>
is true
,
EF
MoveConstructible
(C++17 Table 23)EF
[…]
Remarks: This constructor shall not participate in overload resolution
unlessConstraints: (is_nothrow_move_constructible_v<EF> || is_copy_constructible_v<EF>)
is true
.
Remarks: The expression inside noexcept
is equivalent to is_nothrow_move_constructible_v<EF> || is_nothrow_copy_constructible_v<EF>
.
[…]
Class template unique_resource
[scopeguard.uniqueres]
[…]
Constructors [scopeguard.uniqueres.ctor]
Effects: Value-initializes resource
and deleter
;
execute_on_reset
is initialized
with false
.
Remarks: This constructor shall not participate in overload resolution unlessConstraints:
is_default_constructible_v<R> && is_default_constructible_v<D>
is true
.
RequiresMandates:
The expressions d(r)
, d(RESOURCE)
and deleter(RESOURCE)
are well-formed.
Preconditions:
Calling d(r)
, d(RESOURCE)
or deleter(RESOURCE)
shall havehas well-defined behavior and
shalldoes not throw an exception.
Effects: […]
Throws: […]
Remarks: This constructor shall not participate in overload resolution unless
Constraints: is_constructible_v<R1, RR> &&
is_constructible_v<D , DD> &&
(is_nothrow_constructible_v<R1, RR> || is_constructible_v<R1,RR&>) &&
(is_nothrow_constructible_v<D , DD> || is_constructible_v<D ,DD&>)
is true
. [Note: The first two conditions prohibit initialization
from an rvalue reference when either R1
or D
is a specialization
of reference_wrapper
. — end note]
Remarks: The expression inside
noexcept
is equivalent to […]
[…]
Destructor [scopeguard.uniqueres.dtor]
[…]
Assignment [scopeguard.uniqueres.assign]
RequiresPreconditions:
If is_nothrow_move_assignable_v<R1>
is true
,
R1
shall satisfy the meets the Cpp17MoveAssignable (C++20 Table 28) requirements;
otherwise MoveAssignable
requirements
(C++17 Table 25)R1
shall satisfy the meets the Cpp17CopyAssignable (C++20 Table 29) requirements.
If CopyAssignable
requirements
(C++17 Table 26)is_nothrow_move_assignable_v<D>
is true
,
D
shall satisfy the meets the Cpp17MoveAssignable (C++20 Table 28) requirements;
otherwise MoveAssignable
requirements
(C++17 Table 25)D
shall satisfy the meets the Cpp17CopyAssignable (C++20 Table 29) requirements.
CopyAssignable
requirements
(C++17 Table 26)
Effects: […]
Throws: […]
Remarks: […]
Other member functions [scopeguard.uniqueres.members]
Effects: […]
RequiresMandates:
The expression deleter(r)
shall beis well-formed.
Preconditions: Calling deleter(r)
shall havehas
well-defined behavior and shalldoes not throw an exception.
Effects: […]
Remarks: This function shall not participate in overload resolution unlessConstraints:
the selected assignment expression statement assigning resource
is well-formed.
Effects: Equivalent to execute_on_reset = false
.
Returns: resource
.
Effects: Equivalent to: return *get();
Remarks: This function shall not participate in overload resolution unlessConstraints:
is_pointer_v<R>
is true
and is_void_v<remove_pointer_t<R>>
is false
.
Remarks: The return type is add_lvalue_reference_t<remove_pointer_t<R>>
.
Returns: get()
.
Remarks: This function shall not participate in overload resolution unless
Constraints: is_pointer_v<R>
is true
.
Returns: deleter
.
unique_resource
creation [scopeguard.uniqueres.create]
RequiresMandates:
The expression (resource == invalid ? true : false)
shall beis well-formed.
Preconditions: Evaluation of the expression
(resource == invalid ? true : false)
shall havehas
well-defined behavior and shalldoes not throw an exception.
Effects: […]
[…]
Class template function
[func.wrap.func]
[…]
function
construct/copy/destroy [func.wrap.func.con]
[…]
Effects: function(allocator_arg, ALLOCATOR_OF(*this), std::forward<F>(f)).swap(*this);
Returns: *this
.
Remarks: This assignment operator shall not participate in overload resolution unlessConstraints:
declval<decay_t<F>&>()
is
Callable (C++17 §23.14.13.2)Lvalue-Callable (C++20 §20.14.16.2)
for argument types ArgTypes...
and return type R
.
[…]
function
modifiers [func.wrap.func.mod]
RequiresPreconditions: *this->get_memory_resource() == *other.get_memory_resource()
.
Effects: Interchanges the targets of *this
and other
.
Remarks: The allocators of *this
and other
are not interchanged.
Editorial note: The change from “Callable” to “Lvalue-Callable” was part of the transition from C++14 to C++17 and was previously missed by P1210R0.
Non-owning pointers [memory.observer.ptr]
[…]
observer_ptr
constructors [memory.observer.ptr.ctor]
[…]
Postconditions: get() == other.get()
.
Remarks: This constructor shall not participate in overload resolution unlessConstraints:
W2*
is convertible to W*
.
observer_ptr
observers [memory.observer.ptr.obs]
[…]
RequiresPreconditions: get() != nullptr
is true
.
Returns: *get()
.
Throws: Nothing.
[…]
observer_ptr
hash support [memory.observer.ptr.hash]
The template specialization shall meet the requirements of class template )specialization is enabled (C++20 §20.14.18).
For an object hash
(C++17 §23.14.15p
of type observer_ptr<T>
, hash<observer_ptr<T>>()(p)
shall evaluateevaluates to the same value as hash<T*>()(p.get())
.
Type-erased allocator [memory.type.erased.allocator]
[…]
Additionally, class C
shall meetmeets the following requirements:
C::allocator_type
std::experimental::erased_type
.X.get_memory_resource()
returns rptr
.Header <experimental/memory_resource>
synopsis [memory.resource.syn]
[…]
Alias template resource_adaptor
[memory.resource.adaptor]
resource_adaptor
[memory.resource.adaptor.overview]
[…] In addition to the Cpp17AllocatorRequirements (C++20 §16.5.3.5),
the parameter to Allocator
requirements (C++17 §20.5.3.5)resource_adaptor
shall meet the following additional requirements: […]
[…]
resource_adaptor_imp member functions
[memory.resource.adaptor.mem]
[…]
RequiresPreconditions: p
was previously allocated
using A.allocate
, where A == m_alloc
, and not subsequently deallocated.
Effects: […]
[…]
Algorithms library [algorithms]
[…]
Shuffle [alg.random.shuffle]
[…]
Requires: Preconditions:
RandomAccessIterator
shall satisfy the
requirements of ValueSwappable
(C++17 §20.5.3.2)RandomAccessIterator
meets the Cpp17ValueSwappable requirements (C++20 §16.5.3.2).
Complexity: […]
Remarks: To the extent that the implementation of this function makes use of random numbers,
the per-thread engine (10.1.2.1) shall serveserves as the implementation’s
source of randomness.
Numerics library [numeric]
[…]
Utilities [rand.util]
Function template randint
[rand.util.randint]
A separate per-thread engine of type default_random_engine
(C++17 §29.6.5C++20 §26.6.5),
initialized to an unpredictable state, shall be maintained for each thread.
RequiresPreconditions: a
≤ b
.
Remarks: If the template argument does not meet the requirements for Mandates: The template argument meets the requirements for a template parameter named IntType
, the program is ill-formed
(C++17 §29.6.1.1)IntType
in C++20 §26.6.2.1.
Returns: A random integer i, a
≤ i ≤ b
,
produced from a thread-local instance of uniform_int_distribution<IntType>
(C++17 §29.6.8.2.1C++20 §26.6.8.2.1) invoked with the per-thread engine.
[…]
Editorial instruction: The specification elements should be reordered editorially according to the order provided by [C++20, structure.specifications].