Revised 2018-05-06 at 19:13:12 UTC
Section: 23.7.7 [variant.visit] Status: Tentatively Ready Submitter: Tim Song Opened: 2017-05-31 Last modified: 2018-03-05
Priority: 2
View other active issues in [variant.visit].
View all other issues in [variant.visit].
View all issues with Tentatively Ready status.
Discussion:
[variant.visit]/1 correctly uses "type and value category", but then p3 describes the return type of visit to be "the common type of all possible INVOKE expressions of the Effects: element." The type of an expression is never a reference type, due to [expr]/5 removing the referenceness "prior to any further analysis", so this wording as written says that visit always returns a non-reference type, which is presumably not the intent.
[2017-07 Toronto Monday issue prioritization]
Priority 2; Matt to provide wording
[2018-01-11, Thomas Köppe comments and suggests wording]
The return type of std::visit (originating by P0088R3 accepted during the Oulo 2016 meeting) is currently misspecified and refers only to the common type of all the possible visitation calls, without attention to the value category. This seems unintended, and we should preserve the value category.
[2017-01-24, Daniel comments]
This issue should be reviewed in common with LWG 3052.
[ 2018-02-23 Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4727.
Modify 23.7.7 [variant.visit] as indicated:
template<class Visitor, class... Variants> constexpr see below visit(Visitor&& vis, Variants&&... vars);[…]
-3- Returns: e(m), where m is the pack for which mi is varsi.index() for all 0 <= i < n. The return type isthe type of e(m)decltype(e(m)). […]
Section: 28.4.5 [algorithms.parallel.overloads] Status: Tentatively Ready Submitter: Billy O'Neal III Opened: 2018-02-07 Last modified: 2018-02-20
Priority: 0
View all issues with Tentatively Ready status.
Discussion:
Our compiler throughput friends were hissing at us about throughput regressions in C++17 mode caused by the addition of the parallel algorithms' signatures. One change to reduce the throughput impact would be to remove unnecessary decay here, as LWG has done in other places recently.
[ 2018-02-13 Moved to Tentatively Ready after 7 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4713.
Modify 28.4.5 [algorithms.parallel.overloads] as indicated:
-4- Parallel algorithms shall not participate in overload resolution unless is_execution_policy_v<
decayremove_cvref_t<ExecutionPolicy>> is true.
Section: 30.11.13.1 [fs.rec.dir.itr.members] Status: Tentatively Ready Submitter: Casey Carter Opened: 2018-02-25 Last modified: 2018-03-13
Priority: 0
View other active issues in [fs.rec.dir.itr.members].
View all other issues in [fs.rec.dir.itr.members].
View all issues with Tentatively Ready status.
Discussion:
recursive_directory_iterator::pop is effectively a "supercharged" operator++: it advances the iterator forward as many steps as are necessary to reach the next entry in the parent directory. Just as is the case for operator++, pop must be allowed to invalidate iterator copies to allow efficient implementation. The most efficient fix seems to be borrowing the invalidation wording from 27.2.3 [input.iterators] Table 87's specification for the required ++r expression for input iterators.
[ 2018-03-06 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4727.
Change 30.11.13.1 [fs.rec.dir.itr.members] as indicated:
void pop(); void pop(error_code& ec);-26- Effects: If depth() == 0, set *this to recursive_directory_iterator(). Otherwise, cease iteration of the directory currently being iterated over, and continue iteration over the parent directory.
-?- Postconditions: Any copies of the previous value of *this are no longer required either to be dereferenceable or to be in the domain of ==.
-27- Throws: As specified in 30.11.6 [fs.err.report].
Section: 17.9 [networking.ts::buffer.read.until] Status: Tentatively Ready Submitter: Christopher Kohlhoff Opened: 2018-02-26 Last modified: 2018-03-13
Priority: 0
View all issues with Tentatively Ready status.
Discussion:
Addresses: networking.tsWhen specifying DynamicBuffers and their related operations, early drafts of the Networking TS described the buffers in terms of their "input sequence" and "output sequence". This was changed to "readable bytes" and "writable bytes" respectively. Unfortunately, some instances of "input sequence" were missed in section 17.9 [networking.ts::buffer.read.until].
[ 2018-03-06 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4711.
Change 17.9 [networking.ts::buffer.read.until] as indicated:
template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim, error_code& ec); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim, error_code& ec);-1- Effects: Reads data from the buffer-oriented synchronous read stream (17.1.1 [networking.ts::buffer.stream.reqmts.syncreadstream]) object stream by performing zero or more calls to the stream's read_some member function, until the
-2- Data is placed into the dynamic buffer object b. A mutable buffer sequence (16.2.1) is obtained prior to each read_some call using b.prepare(N), where N is an unspecified value such that N <= max_size() - size(). [Note: Implementations are encouraged to use b.capacity() when determining N, to minimize the number of read_some calls performed on the stream. — end note] After each read_some call, the implementation performs b.commit(n), where n is the return value from read_some. -3- The synchronous read_until operation continues until:input sequencereadable bytes of the dynamic buffer (16.2.4 [networking.ts::buffer.reqmts.dynamicbuffer]) object b containsthe specified delimiter delim.-4- On exit, if the
(3.1) — the
input sequencereadable bytes of b containsthe delimiter delim; or(3.2) — b.size() == b.max_size(); or
(3.3) — an asynchronous read_some operation fails.
input sequencereadable bytes of b containsthe delimiter, ec is set such that !ec is true. Otherwise, if b.size() == b.max_size(), ec is set such that ec == stream_errc::not_found. If b.size() < b.max_size(), ec contains the error_code from the most recent read_some call. -5- Returns: The number ofbytes in the input sequence ofreadable bytes in b up to and including the delimiter, if present. [Note: On completion, the buffer may contain additional bytes following the delimiter. — end note] Otherwise returns 0.
Section: 29.7.3 [valarray.nonmembers] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2018-02-28 Last modified: 2018-03-13
Priority: 0
View all issues with Tentatively Ready status.
Discussion:
The expression (std::valarray<double>{} * 2) is ill-formed, because argument deduction fails for:
template<class T> valarray<T> operator*(const valarray<T>&, const T&);
Is there any reason to try and deduce the argument from the scalar, instead of only deducing from the valarray and allowing implicit conversions to the scalar? i.e.
template<class T> valarray<T> operator*(const valarray<T>&, const typename valarray<T>::value_type&);
[ 2018-03-07 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4727.
Edit 29.7.1 [valarray.syn], header <valarray> synopsis, as indicated:
[…] template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator* (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator* (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator/ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator/ (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator/ (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator% (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator% (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator% (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator+ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator+ (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator+ (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator- (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator- (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator- (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator^ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator^ (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator^ (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator& (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator& (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator& (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator| (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator| (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator| (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator<<(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator<<(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator<<(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator>>(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator>>(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator>>(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator&&(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator&&(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator&&(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator||(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator||(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator||(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator==(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator==(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator==(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator!=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator!=(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator!=(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator< (const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator< (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator< (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator> (const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator> (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator> (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator<=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator<=(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator<=(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator>=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator>=(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator>=(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> abs (const valarray<T>&); template<class T> valarray<T> acos (const valarray<T>&); template<class T> valarray<T> asin (const valarray<T>&); template<class T> valarray<T> atan (const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> atan2(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> cos (const valarray<T>&); template<class T> valarray<T> cosh (const valarray<T>&); template<class T> valarray<T> exp (const valarray<T>&); template<class T> valarray<T> log (const valarray<T>&); template<class T> valarray<T> log10(const valarray<T>&); template<class T> valarray<T> pow(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> pow(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> pow(constTtypename valarray<T>::value_type&, const valarray<T>&); […]
Edit 29.7.3.1 [valarray.binary] as indicated:
[…] template<class T> valarray<T> operator* (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator* (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator/ (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator/ (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator% (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator% (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator+ (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator+ (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator- (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator- (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator^ (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator^ (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator& (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator& (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator| (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator| (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator<<(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator<<(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator>>(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> operator>>(constTtypename valarray<T>::value_type&, const valarray<T>&); […]
Edit 29.7.3.2 [valarray.comparison] as indicated:
[…] template<class T> valarray<bool> operator==(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator==(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator!=(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator!=(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator< (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator< (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator> (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator> (constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator<=(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator<=(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator>=(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator>=(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator&&(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator&&(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator||(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<bool> operator||(constTtypename valarray<T>::value_type&, const valarray<T>&); […]
Edit 29.7.3.3 [valarray.transcend] as indicated:
template<class T> valarray<T> abs (const valarray<T>&); template<class T> valarray<T> acos (const valarray<T>&); template<class T> valarray<T> asin (const valarray<T>&); template<class T> valarray<T> atan (const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> atan2(constTtypename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> cos (const valarray<T>&); template<class T> valarray<T> cosh (const valarray<T>&); template<class T> valarray<T> exp (const valarray<T>&); template<class T> valarray<T> log (const valarray<T>&); template<class T> valarray<T> log10(const valarray<T>&); template<class T> valarray<T> pow (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> pow (const valarray<T>&, constTtypename valarray<T>::value_type&); template<class T> valarray<T> pow (constTtypename valarray<T>::value_type&, const valarray<T>&); […]
Section: 30.11.14.7 [fs.op.create_directory] Status: Tentatively Ready Submitter: Billy O'Neal III Opened: 2018-03-07 Last modified: 2018-03-31
Priority: 0
View all issues with Tentatively Ready status.
Discussion:
LWG 2935 clarified that create_directory is not supposed to report an error if exists(p), even if p is not a directory. However, the P/R there missed the existing_p overloads.
[ 2018-03-27 Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4727.
Edit 30.11.14.7 [fs.op.create_directory] as indicated:
bool create_directory(const path& p, const path& existing_p); bool create_directory(const path& p, const path& existing_p, error_code& ec) noexcept;-4- Effects:
Establishes the postcondition by attempting to createCreates the directory p resolves to, with attributes copied from directory existing_p. The set of attributes copied is operating system dependent. Creation failure because presolves to an existing directory shall not be treated asalready exists is not an error. [Note: For POSIX-based operating systems, the attributes are those copied by native API stat(existing_p.c_str(), &attributes_stat) followed by mkdir(p.c_str(), attributes_stat.st_mode). For Windows-based operating systems, the attributes are those copied by native API CreateDirectoryExW(existing_p.c_str(), p.c_str(), 0). — end note]-5- Postconditions: is_directory(p).[…]
Section: 23.20.3 [charconv.from.chars] Status: Tentatively Ready Submitter: Greg Falcon Opened: 2018-03-12 Last modified: 2018-03-31
Priority: 0
View other active issues in [charconv.from.chars].
View all other issues in [charconv.from.chars].
View all issues with Tentatively Ready status.
Discussion:
from_chars specifies that the '+' character is never matched, but to_chars specifies its output format in terms of printf(), which puts a '+' sign before positive exponents.
Since strtod() matches '+' signs, it is also desirable to accept '+' in exponents, so that code currently using strtod() can be migrated to from_chars() without a breaking semantic change.[ 2018-03-27 Moved to Tentatively Ready after 9 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4727.
Edit 23.20.3 [charconv.from.chars] as indicated:
from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt = chars_format::general);-6- Requires: fmt has the value of one of the enumerators of chars_format.
-7- Effects: The pattern is the expected form of the subject sequence in the "C" locale, as described for strtod, except that
(7.1) — the
onlysign '+'thatmay only appearis '-'in the exponent part;(7.2) […]
(7.3) […]
(7.4) […]
Section: 30.5.3.5 [ios.base.storage] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2018-03-16 Last modified: 2018-03-31
Priority: 0
View other active issues in [ios.base.storage].
View all other issues in [ios.base.storage].
View all issues with Tentatively Ready status.
Discussion:
Is calling iword and pword with a negative argument undefined, or should it cause a failure condition (and return a valid reference)? What about INT_MAX? What about 0?
Using arbitrary indices isn't safe, because the implementation could be already using them for something else. Some replies on the reflector suggested the only reliable argument is one obtained from ios_base::xalloc(). Others pointed out that the iwords and pwords could be stored in sparse arrays, so that any value from INT_MIN to INT_MAX could be a valid key (which might require the implementation to use keys outside that range for its own entries in the arrays). If it's undefined we should add a Requires element to the spec. If invalid indices are supposed to cause a failure we need to define which indices are invalid (and ensure that's something the implementation can check), and specify that it causes a failure.[ 2018-03-27 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4727.
Edit 30.5.3.5 [ios.base.storage] as indicated:
long& iword(int idx);-?- Requires: idx is a value obtained by a call to xalloc.
-3- Effects: If iarray is a null pointer, […] […]void*& pword(int idx);-?- Requires: idx is a value obtained by a call to xalloc.
-5- Effects: If iarray is a null pointer, […] […]
Section: 23.17.5.10 [time.duration.io] Status: Tentatively Ready Submitter: Richard Smith Opened: 2018-04-02 Last modified: 2018-05-06
Priority: 0
View all issues with Tentatively Ready status.
Discussion:
[time.duration.io]p4 says:
For streams where charT has an 8-bit representation, "µs" should be encoded as UTF-8. Otherwise UTF-16 or UTF-32 is encouraged. The implementation may substitute other encodings, including "us".
This choice of encoding is not up to the <chrono> library to decide or encourage. The basic execution character set determines how a mu should be encoded in type char, for instance, and it would be truly bizarre to use a UTF-8 encoding if that character set is, say, Latin-1 or EBCDIC.
I suggest we strike at least the first two sentences of this paragraph, as the meaning of the prior wording is unambiguous without them and confusing with them, and they do not providing any normative requirements (although they do provide recommendations). The third sentence appears to have a normative impact, but it's hard to see how it's legitimate to call "us" an "encoding" of "µs"; it's really just an alternative unit suffix. So how about replacing that paragraph with this:If Period::type is micro, but the character U+00B5 cannot be represented in the encoding used for charT, the unit suffix "us" is used instead of "µs".
(This also removes the permission for an implementation to choose an arbitrary alternative "encoding", which seems undesirable.)
[ 2018-04-23 Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4741.
Edit 23.17.5.10 [time.duration.io] as indicated:
template<class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const duration<Rep, Period>& d);-1- Requires: […]
-2- Effects: […] -3- The units suffix depends on the type Period::type as follows:
[…]
(3.5) — Otherwise, if Period::type is micro, the suffix is "µs" ("\u00b5\u0073").
[…]
(3.21) — Otherwise, the suffix is "[num/den]s".
[…]
-4-For streams where charT has an 8-bit representation, "µs" should be encoded as UTF-8. Otherwise UTF-16 or UTF-32 is encouraged. The implementation may substitute other encodings, including "us"If Period::type is micro, but the character U+00B5 cannot be represented in the encoding used for charT, the unit suffix "us" is used instead of "µs". -5- Returns: os.
Section: 26.7.3.2 [span.cons] Status: Tentatively Ready Submitter: Stephan T. Lavavej Opened: 2018-04-12 Last modified: 2018-05-06
Priority: 0
View other active issues in [span.cons].
View all other issues in [span.cons].
View all issues with Tentatively Ready status.
Discussion:
The span constructors have wording relics that mention an "empty span". It's unnecessary (the behavior is fully specified by the postconditions), but I left it there because I thought it was harmless. It was later pointed out to me that this is actually confusing. Talking about an "empty span" implies that there's just one such thing, but span permits empty() to be true while data() can vary (being null or non-null). (This behavior is very useful; consider how equal_range() behaves.)
To avoid confusion, the "empty span" wording should simply be removed, leaving the constructor behavior unchanged. Editorially, there's also a missing paragraph number.[ 2018-04-24 Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4741.
Edit 26.7.3.2 [span.cons] as indicated:
constexpr span() noexcept;-2- Postconditions: size() == 0 && data() == nullptr. -3- Remarks: This constructor shall not participate in overload resolution unless Extent <= 0 is true.
-1- Effects: Constructs an empty span.constexpr span(pointer ptr, index_type count);-4- Requires: [ptr, ptr + count) shall be a valid range. If extent is not equal to dynamic_extent, then count shall be equal to extent.
-5- Effects: Constructs a span that is a view over the range [ptr, ptr + count).If count is 0 then an empty span is constructed.-6- Postconditions: size() == count && data() == ptr. -?- Throws: Nothing.constexpr span(pointer first, pointer last);-7- Requires: [first, last) shall be a valid range. If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
-8- Effects: Constructs a span that is a view over the range [first, last).If last - first == 0 then an empty span is constructed.-9- Postconditions: size() == last - first && data() == first. -10- Throws: Nothing.
Section: 26.7.3.1 [span.overview] Status: Tentatively Ready Submitter: Stephan T. Lavavej Opened: 2018-04-12 Last modified: 2018-05-06
Priority: 0
View all issues with Tentatively Ready status.
Discussion:
There are multiple issues with how span specifies its iterators:
const_iterator isn't mentioned.
The relationship between iterator and const_iterator isn't specified. (span isn't a container, so it doesn't receive this automatically.)
The iterators should be specified to be constexpr.
By imitating 24.4.2.2 [string.view.iterators]/3 "All requirements on container iterators ([container.requirements]) apply to basic_string_view::const_iterator as well.", we can specify that iterator is convertible to const_iterator.
[ 2018-04-23 Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4741.
Edit 26.7.3.1 [span.overview] as indicated:
-4- The iterator types
for span is a random access iterator and a contiguous iteratorspan::iterator and span::const_iterator are random access iterators (27.2.7 [random.access.iterators]), contiguous iterators (27.2.1 [iterator.requirements.general]), and constexpr iterators (27.2.1 [iterator.requirements.general]). All requirements on container iterators (26.2 [container.requirements]) apply to span::iterator and span::const_iterator as well.
Section: 23.17.5.5 [time.duration.nonmember] Status: Tentatively Ready Submitter: Johel Ernesto Guerrero Peña Opened: 2018-04-17 Last modified: 2018-05-06
Priority: 0
View all other issues in [time.duration.nonmember].
View all issues with Tentatively Ready status.
Discussion:
[time.duration.nonmember]/1 states
In the function descriptions that follow, CD represents the return type of the function.
From what I could find, many definitions of CD in the paragraphs of [time.duration.nonmember] were lifted to [time.duration.nonmember]/1 as cited above. That works for all other paragraphs, but not for [time.duration.nonmember]/10, which the change rendered ill-formed:
template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<Rep1, Rep2> operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);Returns: CD(lhs).count() / CD(rhs).count().
In this case, we want CD to mean common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>. That way, the division has the expected semantics of dividing two quantities of the same dimension.
[ 2018-04-24 Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
Proposed resolution:
This wording is relative to N4741.
Edit 23.17.5.5 [time.duration.nonmember] as indicated:
-1- In the function descriptions that follow, unless stated otherwise, let CD represent
[…]sthe return type of the function.template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<Rep1, Rep2> operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);Let CD be common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>.
-10- Returns: CD(lhs).count() / CD(rhs).count().