Issue 3133: Modernizing numeric type requirements (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.
3133. Modernizing numeric type requirements
Section: 29.2 [numeric.requirements] Status: C++20 Submitter: Tim Song Opened: 2018-07-05 Last modified: 2021-02-25
Priority: 0
View all other issues in [numeric.requirements].
View all issues with C++20 status.
Discussion:
29.2 [numeric.requirements] contains some very old wording that hasn't been changed since C++98 except for issue 2699(i). As a result, it is at once over- and under-restrictive. For example:
- It requires a class to have various member functions, but not that said member functions be actually callable (non-ambiguous, non-deleted) or called by the applicable operations;
- It doesn't disallow function or array types;
- It disallows _ref-qualifier_s on the assignment operator by restricting the signature;
- It bans unary
operator&
for class types, but not enumeration types; and - It tries to impose semantic equivalence requirements on
T
's special member functions, but doesn't require that copying produces an equivalent value to the original.
We can significantly clean up this wording by using the existing named requirements. For ease of review, the following table provides a side-by-side comparison of the current and proposed wording.
Before | After |
---|---|
A C++ program shall instantiate these components only with a type T that satisfies the following requirements: [Footnote … ] | A C++ program shall instantiate these components only with a cv-unqualified object type T that satisfies the Cpp17DefaultConstructible, Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17Destructible |
(1.1) — T is not an abstract class (it has no pure virtual member functions); | Cpp17DefaultConstructible |
(1.2) — T is not a reference type; (1.3) — T is not cv-qualified; | Implied by "cv-unqualified object type" |
(1.4) — If T is a class, it has a public default constructor; | Cpp17DefaultConstructible |
(1.5) — If T is a class, it has a public copy constructor with the signature T::T(const T&); | Cpp17CopyConstructible |
(1.6) — If T is a class, it has a public destructor; | Cpp17Destructible |
(1.7) — If T is a class, it has a public copy assignment operator whose signature is eitherT& T::operator=(const T&) or T& T::operator=(T); | Cpp17CopyAssignable |
(1.8) — If T is a class, its assignment operator, copy and default constructors, and destructor shall correspond to each other in the following sense: (1.8.1) — Initialization of raw storage using the copy constructor on the value of T(), however obtained, is semantically equivalent to value-initialization of the same raw storage. (1.8.2) — Initialization of raw storage using the default constructor, followed by assignment, is semantically equivalent to initialization of raw storage using the copy constructor. (1.8.3) — Destruction of an object, followed by initialization of its raw storage using the copy constructor, is semantically equivalent to assignment to the original object. [Note: […] — _end note_] | These requirements are implied by Cpp17CopyConstructible and Cpp17CopyAssignable's requirement that the value of the copy is equivalent to the source. |
(1.9) — If T is a class, it does not overload unary operator&. | omitted now that we have std::addressof |
[2019-01-20 Reflector prioritization]
Set Priority to 0 and status to Tentatively Ready
Proposed resolution:
This wording is relative to the post-Rapperswil 2018 working draft.
- Edit 29.2 [numeric.requirements] p1 as indicated, striking the entire bulleted list:
-1- The
complex
andvalarray
components are parameterized by the type of information they contain and manipulate. A C++ program shall instantiate these components only with a cv-unqualified object typeT
that satisfies the Cpp17DefaultConstructible, Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17Destructiblefollowingrequirements (16.4.4.2 [utility.arg.requirements]).:[Footnote: … ](1.1) —T
is not an abstract class (it has no pure virtual member functions);[…](1.9) — IfT
is a class, it does not overload unaryoperator&
. - Edit 29.6.2.4 [valarray.access] p3-4 as indicated:
const T& operator[](size_t n) const;
T& operator[](size_t n);-1- Requires:
n < size()
.-2- Returns: […]
-3- Remarks: The expression
~~&~~addressof(a[i+j]) ==~~&~~addressof(a[i]) + j
evaluates totrue
for allsize_t i
andsize_t j
such thati+j < a.size()
.-4- The expression
~~&~~addressof(a[i]) !=~~&~~addressof(b[j])
evaluates totrue
for any two arraysa
andb
and for anysize_t i
andsize_t j
such thati < a.size()
andj < b.size()
. [Note: […] — end note ]