Title
Modernizing numeric type requirements
Status
c++20
Section
[numeric.requirements]
Submitter
Tim Song

Created on 2018-07-05.00:00:00 last changed 45 months ago

Messages

Date: 2019-01-20.16:20:00

Proposed resolution:

This wording is relative to the post-Rapperswil 2018 working draft.

  1. Edit [numeric.requirements] p1 as indicated, striking the entire bulleted list:

    -1- The complex and valarray 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 type T that satisfies the Cpp17DefaultConstructible, Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17Destructiblefollowing requirements ([utility.arg.requirements]). :[Footnote: … ]

    (1.1) — T is not an abstract class (it has no pure virtual member functions);

    […]

    (1.9) — If T is a class, it does not overload unary operator&.

  2. Edit [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 to true for all size_t i and size_t j such that i+j < a.size().

    -4- The expression &addressof(a[i]) != &addressof(b[j]) evaluates to true for any two arrays a and b and for any size_t i and size_t j such that i < a.size() and j < b.size(). [Note: […] — end note ]

Date: 2019-01-20.00:00:00

[ 2019-01-20 Reflector prioritization ]

Set Priority to 0 and status to Tentatively Ready

Date: 2018-07-05.00:00:00

[numeric.requirements] contains some very old wording that hasn't been changed since C++98 except for issue 2699. 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-qualifiers 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 Cpp17Destructiblefollowing requirements ([utility.arg.requirements]).:
(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 either T& 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
History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2019-02-26 17:40:23adminsetstatus: voting -> wp
2019-01-21 04:50:04adminsetstatus: ready -> voting
2019-01-20 16:20:00adminsetmessages: + msg10289
2019-01-20 16:20:00adminsetstatus: new -> ready
2018-07-06 05:57:25adminsetmessages: + msg10012
2018-07-05 00:00:00admincreate