Revised 2015-04-10 at 03:04:29 UTC
Section: 23.2 [container.requirements] Status: Tentatively NAD Submitter: Paolo Carlini Opened: 2007-11-11 Last modified: 2015-04-08
View other active issues in [container.requirements].
View all other issues in [container.requirements].
View all issues with Tentatively NAD status.
Discussion:
In an emplace member function the function parameter pack may be bound to a priori unlimited number of objects: some or all of them can be elements of the container itself. Apparently, in order to conform to the blanket statement 23.2 [container.requirements]/11, the implementation must check all of them for that possibility. A possible solution can involve extending the exception in 23.2 [container.requirements]/12 also to the emplace member. As a side note, the push_back and push_front member functions are luckily not affected by this problem, can be efficiently implemented anyway.
[ Related to 767 and to 2164 ]
[ Bellevue: ]
The proposed addition (13) is partially redundant with the existing paragraph 12. Why was the qualifier "rvalues" added to paragraph 12? Why does it not cover subelements and pointers?
Resolution: Alan Talbot to rework language, then set state to Review.
[ 2009-07 Frankfurt ]
The problem is broader than emplace. The LWG doesn't feel that it knows how to write wording that prohibits all of the problematic use cases at this time.
NAD Future.
[2015-02 Cologne]
LWG believes that 2164 addresses this issue and therefore considers 760 as NAD.
Proposed resolution:
Add after 23.2 [container.requirements]/12:
-12- Objects passed to member functions of a container as rvalue references shall not be elements of that container. No diagnostic required.
-13- Objects bound to the function parameter pack of the emplace member function shall not be elements or sub-objects of elements of the container. No diagnostic required.
Section: 23.4.4 [map] Status: Tentatively Ready Submitter: Christopher Jefferson Opened: 2011-05-18 Last modified: 2015-04-08
View all other issues in [map].
View all issues with Tentatively Ready status.
Discussion:
map::erase (and several related methods) took an iterator in C++03, but take a const_iterator in C++0x. This breaks code where the map's key_type has a constructor which accepts an iterator (for example a template constructor), as the compiler cannot choose between erase(const key_type&) and erase(const_iterator).
#include <map> struct X { template<typename T> X(T&) {} }; bool operator<(const X&, const X&) { return false; } void erasor(std::map<X,int>& s, X x) { std::map<X,int>::iterator it = s.find(x); if (it != s.end()) s.erase(it); }
[ 2011 Bloomington ]
This issue affects only associative container erase calls, and is not more general, as these are the only functions that are also overloaded on another single arguement that might cause confusion - the erase by key method. The complete resolution should simply restore the iterator overload in addition to the const_iterator overload for all eight associative containers.
Proposed wording supplied by Alan Talbot, and moved to Review.
[2012, Kona]
Moved back to Open by post-meeting issues processing group.
Pablo very unhappy about case of breaking code with ambiguous conversion between both iterator types.
Alisdair strongly in favor of proposed resolution, this change from C++11 bit Chris in real code, and it took a while to track down the cause.
Move to open, bring in front of a larger group
Proposed wording from Jeremiah: erase(key) shall not participate in overload resolution if iterator is convertible to key. Note that this means making erase(key) a template-method
Poll Chris to find out if he already fixed his code, or fixed his library
Jeremiah - allow both overloads, but enable_if the const_iterator form as a template, requiring is_same to match only const_iterator.
Poll PJ to see if he has already applied this fix?
[2015-02 Cologne]
AM: To summarize, we changed a signature and code broke. At what point do we stop and accept breakage in increasingly obscure code? VV: libc++ is still broken, but libstdc++ works, so they've fixed this — perhaps using this PR? [Checks] Yes, libstdc++ uses this solution, and has a comment pointing to LWG 2059. AM: This issue hasn't been looked at since Kona. In any case, we already have implementation experience now.
AM: I'd say let's ship it. We already have implementation experience (libstdc++ and MSVS). MC: And "tentatively ready" lets me try to implement this and see how it works.Proposed resolution:
Editorial note: The following things are different between 23.2.4 [associative.reqmts] p.8 and 23.2.5 [unord.req] p.10. These should probably be reconciled.
- First uses the convention "denotes"; second uses the convention "is".
- First redundantly says: "If no such element exists, returns a.end()." in erase table entry, second does not.
23.2.4 [associative.reqmts] Associative containers
8 In Table 102, X denotes an associative container class, a denotes a value of X, a_uniq denotes a value of X when X supports unique keys, a_eq denotes a value of X when X supports multiple keys, u denotes an identifier, i and j satisfy input iterator requirements and refer to elements implicitly convertible to value_type, [i,j) denotes a valid range, p denotes a valid const iterator to a, q denotes a valid dereferenceable const iterator to a, r denotes a valid dereferenceable iterator to a, [q1, q2) denotes a valid range of const iterators in a, il designates an object of type initializer_list<value_type>, t denotes a value of X::value_type, k denotes a value of X::key_type and c denotes a value of type X::key_compare. A denotes the storage allocator used by X, if any, or std::allocator<X::value_type> otherwise, and m denotes an allocator of a type convertible to A.
23.2.4 [associative.reqmts] Associative containers Table 102
Add row:
a.erase(r) | iterator | erases the element pointed to by r. Returns an iterator pointing to the element immediately following r prior to the element being erased. If no such element exists, returns a.end(). | amortized constant |
23.2.5 [unord.req] Unordered associative containers
10 In table 103: X is an unordered associative container class, a is an object of type X, b is a possibly const object of type X, a_uniq is an object of type X when X supports unique keys, a_eq is an object of type X when X supports equivalent keys, i and j are input iterators that refer to value_type, [i, j) is a valid range, p and q2 are valid const iterators to a, q and q1 are valid dereferenceable const iterators to a, r is a valid dereferenceable iterator to a, [q1,q2) is a valid range in a, il designates an object of type initializer_list<value_type>, t is a value of type X::value_type, k is a value of type key_type, hf is a possibly const value of type hasher, eq is a possibly const value of type key_equal, n is a value of type size_type, and z is a value of type float.
23.2.5 [unord.req] Unordered associative containers Table 103
Add row:
a.erase(r) | iterator | Erases the element pointed to by r. Returns the iterator immediately following r prior to the erasure. | Average case O(1), worst case O(a.size()). |
23.4.4.1 [map.overview] Class template map overview p. 2
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
23.4.5.1 [multimap.overview] Class template multimap overview p. 2
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
23.4.6.1 [set.overview] Class template set overview p. 2
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
23.4.7.1 [multiset.overview] Class template multiset overview
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
23.5.4.1 [unord.map.overview] Class template unordered_map overview p. 3
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
23.5.5.1 [unord.multimap.overview] Class template unordered_multimap overview p. 3
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
23.5.6.1 [unord.set.overview] Class template unordered_set overview p. 3
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
23.5.7.1 [unord.multiset.overview] Class template unordered_multiset overview p. 3
iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last);
C.2.13 [diff.cpp03.containers] C.2.12 Clause 23: containers library
23.2.3, 23.2.4
Change: Signature changes: from iterator to const_iterator parameters
Rationale: Overspecification. Effects: The signatures of the following member functions changed from taking an iterator to taking a const_iterator:
Valid C++ 2003 code that uses these functions may fail to compile with this International Standard.
Section: 23.4.6.2 [set.cons] Status: Tentatively Ready Submitter: Jens Maurer Opened: 2011-08-20 Last modified: 2015-04-08
View all issues with Tentatively Ready status.
Discussion:
23.4.6.2 [set.cons] paragraph 4 says:
Requires: If the iterator's dereference operator returns an lvalue or a non-const rvalue, then Key shall be CopyConstructible.
I'm confused why a "non-const rvalue" for the return value of the iterator would require CopyConstructible; isn't that exactly the situation when you'd want to apply the move constructor?
The corresponding requirement for multimap seems better in that regard ([multimap.cons] paragraph 3):Requires: If the iterator's dereference operator returns an lvalue or a const rvalue pair<key_type, mapped_type>, then both key_type and mapped_type shall be CopyConstructible.
Obviously, if I have a const rvalue, I can't apply the move constructor (which will likely attempt modify its argument).
Dave Abrahams: I think you are right. Proposed resolution: drop "non-" from 23.4.6.2 [set.cons] paragraph 3.[2012, Kona]
The wording is in this area will be affected by Pablo's paper being adopted at this meeting. Wait for that paper to be applied before visiting this issue - deliberately leave in New status until the next meeting.
Proposed resolution from Kona 2012:
This wording is relative to the FDIS.
Change 23.4.6.2 [set.cons] p3 as follows:
template <class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());-3- Effects: Constructs an empty set using the specified comparison object and allocator, and inserts elements from the range [first,last).
-4- Requires: If the iterator's dereference operator returns an lvalue or anon-const rvalue, then Key shall be CopyConstructible. -5- Complexity: Linear in N if the range [first,last) is already sorted using comp and otherwise N logN, where N is last - first.
[2014-05-18, Daniel comments]
According to Pablo, the current P/R correctly incorporates the changes from his paper (which was adopted in Kona)
[2014-06-10, STL comments and suggests better wording]
N1858 was voted into WP N2284 but was "(reworded)", introducing the "non-const" damage.
N1858 wanted to add this for map:Requires: Does not require CopyConstructible of either key_type or mapped_type if the dereferenced InputIterator returns a non-const rvalue pair<key_type, mapped_type>. Otherwise CopyConstructible is required for both key_type and mapped_type.
And this for set:
Requires: Key must be CopyConstructible only if the dereferenced InputIterator returns an lvalue or const rvalue.
(And similarly for multi.)
This was reworded to N2284 23.3.1.1 [map.cons]/3 and N2284 23.3.3.1 [set.cons]/4, and it slightly changed over the years into N3936 23.4.4.2 [map.cons]/3 and N3936 23.4.6.2 [set.cons]/4. In 2005/2007, this was the best known way to say "hey, we should try to move this stuff", as the fine-grained element requirements were taking shape. Then in 2010, N3173 was voted into WP N3225, adding the definition of EmplaceConstructible and modifying the container requirements tables to make the range constructors require EmplaceConstructible. After looking at this history and double-checking our implementation (where map/set range construction goes through emplacement, with absolutely no special-casing for map's pairs), I am convinced that N3173 superseded N1858 here. (Range-insert() and the unordered containers are unaffected.)Previous resolution [SUPERSEDED]:
This wording is relative to the N3936.
Change 23.4.6.2 [set.cons] p4 as follows:
template <class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());-3- Effects: Constructs an empty set using the specified comparison object and allocator, and inserts elements from the range [first,last).
-4- Requires: If the iterator's indirection operator returns an lvalue or anon-const rvalue, then Key shall be CopyInsertible into *this. -5- Complexity: Linear in N if the range [first,last) is already sorted using comp and otherwise N logN, where N is last - first.
[2015-02 Cologne]
GR: Do requirements supersede rather than compose [container requirements and per-function requirements]? AM: Yes, they supersede.
AM: This looks good. Ready? Agreement.Proposed resolution:
This wording is relative to the N4296.
Remove 23.4.4.2 [map.cons] p3:
template <class InputIterator> map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-3- Requires: If the iterator's indirection operator returns an lvalue or a const rvalue pair<key_type, mapped_type>, then both key_type and mapped_type shall be CopyInsertible into *this.
Remove 23.4.5.2 [multimap.cons] p3:
template <class InputIterator> multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-3- Requires: If the iterator's indirection operator returns an lvalue or a const rvalue pair<key_type, mapped_type>, then both key_type and mapped_type shall be CopyInsertible into *this.
Remove 23.4.6.2 [set.cons] p4:
template <class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-4- Requires: If the iterator's indirection operator returns an lvalue or a non-const rvalue, then Key shall be CopyInsertible into *this.
Remove 23.4.7.2 [multiset.cons] p3:
template <class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-3- Requires: If the iterator's indirection operator returns an lvalue or a const rvalue, then Key shall be CopyInsertible into *this.
Section: 25.4.7 [alg.min.max] Status: Tentatively Ready Submitter: Juan Soulie Opened: 2013-01-26 Last modified: 2015-04-08
View other active issues in [alg.min.max].
View all other issues in [alg.min.max].
View all issues with Tentatively Ready status.
Discussion:
25.4.7 [alg.min.max] requires type T in min, max, and minmax to be LessThanComparable, but I don't believe this should be required for the versions that take a Compare argument.
Paragraphs 1 to 4 of 25.4 [alg.sorting] should apply anyway, although I'm not sure about Compare being required to induce a strict weak ordering here. Further, min and max also lack formal complexity guarantees.[2014-06-07 Daniel comments and provides wording]
Certainly, the functions with Compare should not impose LessThanComparable requirements.
In regard to the question whether a strict weak ordering should be required as implied by the Compare requirements, I would like to point out that this is requirement is in fact needed, because the specification of the normative Remarks elements (e.g. "Returns the first argument when the arguments are equivalent.") do depend on the existence of a equivalence relation that can be relied on and this is also consistent with the same strict weak ordering requirement that is indirectly imposed by the LessThanComparable requirement set for functions referring to operator< (Let me note that the very same StrictWeakOrder language concept had intentionally been required for similar reasons during "concept-time" in N2914).[2015-02 Cologne]
JY: We have library-wide requirements that Comp induce a strict weak ordering.
JY/MC: The un-marked-up "Complexity" (p16) is wrong. DK: I'll fix that. DK will update the wording for Lenexa.[2015-03-30 Daniel comments]
The Complexity element of p16 is correct, but some others involving initializer_list arguments are wrong.
[2015-04-02 Library reflector vote]
The issue has been identified as Tentatively Ready based on six votes in favour.
Proposed resolution:
This wording is relative to N4296.
Change 25.4.7 [alg.min.max] as indicated:
template<class T> constexpr const T& min(const T& a, const T& b); template<class T, class Compare> constexpr const T& min(const T& a, const T& b, Compare comp);-1- Requires: For the first form, type T shall be
-2- Returns: The smaller value. -3- Remarks: Returns the first argument when the arguments are equivalent. -?- Complexity: Exactly one comparison.Type T isLessThanComparable (Table 18).template<class T> constexpr T min(initializer_list<T> t); template<class T, class Compare> constexpr T min(initializer_list<T> t, Compare comp);-4- Requires: T
-5- Returns: […] -6- Remarks: […] -?- Complexity: Exactly t.size() - 1 comparisons.is LessThanComparable andshall be CopyConstructible and t.size() > 0. For the first form, type T shall be LessThanComparable.template<class T> constexpr const T& max(const T& a, const T& b); template<class T, class Compare> constexpr const T& max(const T& a, const T& b, Compare comp);-7- Requires: For the first form, type T shall be
-8- Returns: […] -9- Remarks: […] -?- Complexity: Exactly one comparison.Type T isLessThanComparable (Table 18).template<class T> constexpr T max(initializer_list<T> t); template<class T, class Compare> constexpr T max(initializer_list<T> t, Compare comp);-10- Requires: T
-11- Returns: […] -12- Remarks: […] -?- Complexity: Exactly t.size() - 1 comparisons.is LessThanComparable andshall be CopyConstructible and t.size() > 0. For the first form, type T shall be LessThanComparable.template<class T> constexpr pair<const T&, const T&> minmax(const T& a, const T& b); template<class T, class Compare> constexpr pair<const T&, const T&> minmax(const T& a, const T& b, Compare comp);-13- Requires: For the first form, t
-14- Returns: […] -15- Remarks: […] -16- Complexity: Exactly one comparison.Type T shall be LessThanComparable (Table 18).template<class T> constexpr pair<T, T> minmax(initializer_list<T> t); template<class T, class Compare> constexpr pair<T, T> minmax(initializer_list<T> t, Compare comp);-17- Requires: T
-18- Returns: […] -19- Remarks: […] -20- Complexity: At most (3/2) * t.size() applications of the corresponding predicate.is LessThanComparable andshall be CopyConstructible and t.size() > 0. For the first form, type T shall be LessThanComparable.
Section: 20.8.2.2.5 [util.smartptr.shared.obs] Status: Tentatively NAD Submitter: Stephan T. Lavavej Opened: 2013-10-05 Last modified: 2015-04-08
View other active issues in [util.smartptr.shared.obs].
View all other issues in [util.smartptr.shared.obs].
View all issues with Tentatively NAD status.
Discussion:
20.8.1.2.4 [unique.ptr.single.observers]/3: "pointer operator->() const noexcept; Requires: get() != nullptr."
20.8.2.2.5 [util.smartptr.shared.obs]/2: "T& operator*() const noexcept; Requires: get() != 0." 20.8.2.2.5 [util.smartptr.shared.obs]/5: "T* operator->() const noexcept; Requires: get() != 0." Narrow-contract functions should not be noexcept.[2014-02-15 Issaquah]
Issue is contentious, raise to P2.
[2015-02 Cologne]
AM: This ship has sailed. JM: What's the issue? AM: operator-> has narrow contract and should never have had noexcept. DK: Not quite. We explicitly called out that for shared_ptr this is fine. You said so in your "narrow contract" paper. GR: This would be a fairly major regression in the design of {unique,shared}_ptr over raw pointers; raw pointer dereferencing is noexcept. It's not a performance regression but a usability regression. AM: Do we expect users to query noexpect on dereference expressions? Room: Yes. VV: We don't just expect it, we have seen it. JM: Yes, users may be querying something like noexcept(x->y) and expect to be checking y, but silently end up checking x->.
Close as NAD, with explanation from GR. Previous resolution [SUPERSEDED]:This wording is relative to N3691.
In 20.8.1.2 [unique.ptr.single]/1, class template unique_ptr synopsis for single objects, change as indicated:
pointer operator->() constnoexcept;In 20.8.1.2.4 [unique.ptr.single.observers] change as indicated:
pointer operator->() constnoexcept;-3- Requires: get() != nullptr.
-4- Returns: get(). -?- Throws: Nothing. -5- Note: use typically requires that T be a complete type.In 20.8.2.2 [util.smartptr.shared]/1, class template shared_ptr synopsis, change as indicated:
T& operator*() constnoexcept; T* operator->() constnoexcept;In 20.8.2.2.5 [util.smartptr.shared.obs] change as indicated:
T& operator*() constnoexcept;-2- Requires: get() != 0.
-3- Returns: *get(). -?- Throws: Nothing. -4- Remarks: When T is void, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.T* operator->() constnoexcept;-5- Requires: get() != 0.
-6- Returns: get(). -?- Throws: Nothing.
[2015-03-03, Geoffrey provides rationale]
Rationale:
It is by design that these members are noexcept, and changing that now would be a substantial regression in functionality. These classes were designed to substitute for plain pointers as transparently as possible, so since those operations are effectively noexcept on plain pointers, they should be noexcept on unique_ptr and shared_ptr as well. This matters in practice because we expect these members to be used fairly often inside the noexcept operator, and such code could be broken by this change. These design considerations override our general policy against noexcept for narrow-contract functions.
It is notable that N3279, which proposed this policy, did not propose striking noexcept from these operations. It's not clear if the omission of operator* and operator-> was an oversight, or an intentional reflection of the above considerations. N3279 was based on N3248 by the same authors, which states that:"Most applications of noexcept for unique_ptr and shared_ptr are on functions with wide contracts. However, there are preconditions on the atomic access functions, so these should lose the specification."
Proposed resolution:
Section: 25.4.7 [alg.min.max] Status: Tentatively Ready Submitter: Marc Glisse Opened: 2014-02-21 Last modified: 2015-04-08
View other active issues in [alg.min.max].
View all other issues in [alg.min.max].
View all issues with Tentatively Ready status.
Discussion:
As part of the resolution for LWG issue 2350, max(initializer_list) was marked as constexpr. Looking at two implementations of this function (libstdc++ and libc++), both implement it in terms of max_element, which is not marked as constexpr. This is inconsistent and forces some small amount of code duplication in the implementation. Unless we remove constexpr from this overload of max, I believe we should add constexpr to max_element.
[2015-02 Cologne]
AM: Can we implement this with the C++14 constexpr rules? JM: Yes. AM: Ready? [Yes]
Accepted.Proposed resolution:
This wording is relative to N3936.
In 25.1 [algorithms.general], header <algorithm> synopsis, and 25.4.7 [alg.min.max], change as indicated (add constexpr to every signature from the first min_element to the second minmax_element)::
template<class ForwardIterator> constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp); […] template<class ForwardIterator> constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp); […] template<class ForwardIterator> constexpr pair<ForwardIterator, ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr pair<ForwardIterator, ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last, Compare comp);
Section: 18.6.2.1 [bad.alloc], 18.6.2.2 [new.badlength], 18.7.2 [bad.cast], 18.7.3 [bad.typeid], 18.8.2 [bad.exception] Status: Tentatively Ready Submitter: Andy Sawyer Opened: 2014-03-31 Last modified: 2015-04-08
View all issues with Tentatively Ready status.
Discussion:
I think we have an issue with the specification of some of the standard exception types. In particular, several of them have default constructors with remarks to the effect that "The result of calling what() on the newly constructed object is implementation-defined". (In some cases this is contradictory to a further specification of what(), which is specified to return an implementation-defined NTBS.)
Previous resolution from Andy [SUPERSEDED]:
This wording is relative to N3936.
Edit 18.6.2.1 [bad.alloc] p3 as indicated:
bad_alloc() noexcept;[…]
-3- Remarks:The result of calling what() on the newly constructed object is implementation-definedwhat() returns an implementation-defined NTBS.Edit 18.6.2.2 [new.badlength] p3 as indicated: [Drafting note: Added the Postcondition, since we don't say anything else about bad_array_new_length::what() — end of note]
bad_array_new_length() noexcept;[…]
-3-RemarksPostcondition:The result of calling what() on the newly constructed object is implementation-definedwhat() returns an implementation-defined NTBS.Edit 18.7.2 [bad.cast] p3 as indicated:
bad_cast() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined..Edit 18.7.3 [bad.typeid] p3 as indicated:
bad_typeid() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined..Edit 18.8.2 [bad.exception] p3 as indicated:
bad_exception() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined..
[2014-06-17, Rapperswil]
Jonathan provides alternative wording.
[2015-02, Cologne]
NJ: I don't know why we need the explict statement about what() here, since bad_array_new_length
already derives.
AM: yes.
NJ: Then "what()" is missing from the synopsis.
AM: Yes, that's an error and it needs to be added.
Proposed resolution:
This wording is relative to N4296.
Edit 18.6.2.1 [bad.alloc] p3 as indicated:
bad_alloc() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined.
Edit 18.6.2.1 [bad.alloc] p5 as indicated:
virtual const char* what() const noexcept;-5- Returns: An implementation-defined NTBS.
-?- Remarks: The message may be a null-terminated multibyte string (17.5.2.1.4.2), suitable for conversion and display as a wstring (21.3, 22.4.1.4).
Edit class bad_array_new_length synopsis 18.6.2.2 [new.badlength] as indicated:
namespace std { class bad_array_new_length : public bad_alloc { public: bad_array_new_length() noexcept; virtual const char* what() const noexcept; }; }
Edit 18.6.2.2 [new.badlength] as indicated:
bad_array_new_length() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined.virtual const char* what() const noexcept;-?- Returns: An implementation-defined NTBS.
-?- Remarks: The message may be a null-terminated multibyte string (17.5.2.1.4.2), suitable for conversion and display as a wstring (21.3, 22.4.1.4).
Edit 18.7.2 [bad.cast] p3 as indicated:
bad_cast() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined..
Edit 18.7.3 [bad.typeid] p3 as indicated:
bad_typeid() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined..
Edit 18.8.2 [bad.exception] p3 as indicated:
bad_exception() noexcept;[…]
-3- Remarks: The result of calling what() on the newly constructed object is implementation-defined..
Section: X [mods.util.smartptr.shared.const] Status: Tentatively Ready Submitter: Jeffrey Yasskin Opened: 2014-06-16 Last modified: 2015-04-08
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts
The proposed resolution for LWG 2399 doesn't apply cleanly to the Fundamentals TS, but the issue is still present.
[2015-02, Cologne]
Unanimous consent.
Proposed resolution:
This wording is relative to N4023 in regard to fundamental-ts changes.
In fundamental-ts, change [mods.util.smartptr.shared.const] p34 as indicated:
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);-34-
-35- Effects: Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type, otherwise shared_ptr(r.release(), ref(r.get_deleter())). -36- Exception safety: If an exception is thrown, the constructor has no effect.RequiresRemarks: This constructor shall not participate in overload resolution unless Y*shall beis compatible with T*.
Section: 20.8.2.2.1 [util.smartptr.shared.const] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2014-07-03 Last modified: 2015-04-08
View all other issues in [util.smartptr.shared.const].
View all issues with Tentatively Ready status.
Discussion:
unique_ptr guarantees that it will not invoke its deleter if it stores a null pointer, which is useful for deleters that must not be called with a null pointer e.g.
unique_ptr<FILE, int(*)(FILE*)> fptr(file, &::fclose);
However, shared_ptr does invoke the deleter if it owns a null pointer, which is a silent change in behaviour when transferring ownership from unique_ptr to shared_ptr. That means the following leads to undefined behaviour:
std:shared_ptr<FILE> fp = std::move(fptr);
Peter Dimov's suggested fix is to construct an empty shared_ptr from a unique_ptr that contains a null pointer.
[2015-01-18 Library reflector vote]
The issue has been identified as Tentatively Ready based on eight votes in favour.
Proposed resolution:
This wording is relative to N4296.
Change 20.8.2.2.1 [util.smartptr.shared.const] p29 as indicated:
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);[…]
-29- Effects: If r.get() == nullptr, equivalent to shared_ptr(). Otherwise, if D is not a reference type, equivalent to shared_ptr(r.release(), r.get_deleter()). Otherwise, equivalent to shared_ptr(r.release(), ref(r.get_deleter()))Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type, otherwise shared_ptr(r.release(), ref(r.get_deleter())).
Section: X [tuple.apply] Status: Tentatively Ready Submitter: Zhihao Yuan Opened: 2014-07-08 Last modified: 2015-04-08
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts
The definition of apply present in §3.2.2 [tuple.apply] prevents this function template to be used with pointer to members type passed as the first argument.
Effects: […] return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
This makes this utility inconsistent with other standard library components and limits its usability.
We propose to define its functionally in terms of INVOKE.[2015-02, Cologne]
DK: We should use the new std::invoke.
TK: Is this a defect?
AM: std::invoke goes into C++17, and this is a defect against a TS based on C++14. We can change this later,
but now leave it as INVOKE.
GR: The TS lets you have Editor's Notes, so leave a note to make that change for C++17.
Proposed resolution:
This wording is relative to N4081 in regard to fundamental-ts changes.
Edit §3.2.2 [tuple.apply] paragraph 2:
template <class F, class Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t);-2- Effects: Given the exposition only function
template <class F, class Tuple, size_t... I> constexpr decltype(auto) apply_impl( // exposition only F&& f, Tuple&& t, index_sequence<I...>) { return INVOKE(std::forward<F>(f)(, std::get<I>(std::forward<Tuple>(t))...); }[…]
Section: 24.2.2 [iterator.iterators] Status: Tentatively Ready Submitter: Stephan T. Lavavej Opened: 2014-10-01 Last modified: 2015-04-08
View all other issues in [iterator.iterators].
View all issues with Tentatively Ready status.
Discussion:
24.2.2 [iterator.iterators]/2 requires an Iterator's *r to return reference, i.e. iterator_traits<X>::reference according to 24.2.1 [iterator.requirements.general]/11.
24.2.4 [output.iterators]/1 requires an OutputIterator's *r = o to do its job, so *r clearly can't return void. 24.4.1 [iterator.traits]/1 says: "In the case of an output iterator, the typesiterator_traits<Iterator>::difference_type iterator_traits<Iterator>::value_type iterator_traits<Iterator>::reference iterator_traits<Iterator>::pointer
may be defined as void."
This is contradictory. I suggest fixing this by moving the offending requirement down from Iterator to InputIterator, and making Iterator say that *r returns an unspecified type. This will have the following effects:Output-only iterators will inherit Iterator's "*r returns unspecified" requirement, while 24.4.1 [iterator.traits]/1 clearly permits reference/etc. to be void.
Input-or-stronger iterators (whether constant or mutable) are unaffected — they still have to satisfy "*r returns reference", they're just getting that requirement from InputIterator instead of Iterator.
[2015-02 Cologne]
EF: This is related to 2438. MC: I'd like to take up 2438 right after this.
AM: Does anyone think this is wrong? GR: Why do we give output iterators to have reference type void? AM: we've mandated that certain output iterators define it as void since 1998. GR: Oh OK, I'm satisfied. Accepted. And 2438 is already Ready.Proposed resolution:
This wording is relative to N3936.
In 24.2.2 [iterator.iterators] Table 106 "Iterator requirements" change as indicated:
Table 106 — Iterator requirements Expression Return type Operational
semanticsAssertion/note pre-/post-condition *r referenceunspecifiedpre: r is dereferenceable. …
In 24.2.3 [input.iterators] Table 107 "Input iterator requirements" change as indicated:
Table 107 — Input iterator requirements (in addition to Iterator) Expression Return type Operational
semanticsAssertion/note pre-/post-condition … *a reference, convertible to T […] …
Section: 23.2.1 [container.requirements.general] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2014-10-18 Last modified: 2015-04-08
View other active issues in [container.requirements.general].
View all other issues in [container.requirements.general].
View all issues with Tentatively Ready status.
Discussion:
According to Table 96 — "Container requirements" the specification:
note: the destructor is applied to every element of a; any memory obtained is deallocated.
The initial "note:" can be read as if that part of the specification would not be normative (This note form differs from footnotes in tables, which have normative meaning).
It seems that this initial part of the specification exists since C++98. But comparing with the similar SGI Container specification there is no evidence for that being intended to be non-normative.[2015-02, Cologne]
NJ: If we fix this, we should also fix it elsewhere. Oh, this is the only place?
GR: If this is intended to be different from elsewhere, we should make sure.
AM: valarray specifies this without the "note:".
DK: valarray requires trivially destructible types!
GR: That's good enough for me.
NJ: First time valarray has been useful for something!
Proposed resolution:
This wording is relative to N4140.
Change 23.2.1 [container.requirements.general], Table 96 — "Container requirements", as indicated:
Table 96 — Container requirements Expression Return type Operational
semanticsAssertion/note
pre-/post-conditionComplexity … (&a)->~X() void note:the destructor
is applied to every
element of a; any
memory obtained is deallocated.linear …
Section: 20.7.10 [storage.iterator] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2014-11-11 Last modified: 2015-04-08
View other active issues in [storage.iterator].
View all other issues in [storage.iterator].
View all issues with Tentatively Ready status.
Discussion:
Eric Niebler pointed out that raw_storage_iterator should give access to the OutputIterator it wraps.
This helps alleviate the exception-safety issue pointed out in the discussion of LWG 2127, as an exception can be caught and then destructors can be run for the constructed elements in the range [begin, raw.base())[2015-02 Cologne]
NJ: Is this "const" correct [in "base()"]? DK: Yes, we always do that. NJ: And the output iterator is not qualifying in any way? AM/DK: That wouldn't make sense. NJ: OK.
VV: What did LEWG say about this feature request? In other words, why is this a library issue? AM: LEWG/JY thought this wouldn't be a contentious issue. NJ: I really hope the split of LEWG and LWG will be fixed soon, since it's only wasting time. VV: So you want to spend even more of your time on discussions that LEWG has? AM: I think this specified correctly. I'm not wild about it. But no longer bothered to stand in its way. GR: Why do we need to repeat the type in "Returns" even though it's part of the synopsis? AM: Good point, but not worth fixing. NJ: Why is "base()" for reverse_iterator commented with "// explicit"? AM: I guess in 1998 that was the only way to say this. AM: So, it's tentatively ready.Proposed resolution:
This wording is relative to N4140.
Add a new function to the synopsis in 20.7.10 [storage.iterator] p1:
namespace std { template <class OutputIterator, class T> class raw_storage_iterator : public iterator<output_iterator_tag,void,void,void,void> { public: explicit raw_storage_iterator(OutputIterator x); raw_storage_iterator<OutputIterator,T>& operator*(); raw_storage_iterator<OutputIterator,T>& operator=(const T& element); raw_storage_iterator<OutputIterator,T>& operator++(); raw_storage_iterator<OutputIterator,T> operator++(int); OutputIterator base() const; }; }
Insert the new function and a new paragraph series after p7:
OutputIterator base() const;-?- Returns: An iterator of type OutputIterator that points to the same value as *this points to.
Section: 17.6.3.5 [allocator.requirements] Status: Tentatively Ready Submitter: Pablo Halpern Opened: 2014-11-11 Last modified: 2015-04-08
View other active issues in [allocator.requirements].
View all other issues in [allocator.requirements].
View all issues with Tentatively Ready status.
Discussion:
17.6.3.5 [allocator.requirements]/4 in the 2014-10 WP (N4140), says:
An allocator type X shall satisfy the requirements of CopyConstructible (17.6.3.1). The X::pointer, X::const_pointer, X::void_pointer, and X::const_void_pointer types shall satisfy the requirements of NullablePointer (17.6.3.3). No constructor, comparison operator, copy operation, move operation, or swap operation on these types shall exit via an exception. X::pointer and X::const_pointer shall also satisfy the requirements for a random access iterator (24.2).
The words "these types" would normally apply only to the previous sentence only, i.e., only to the pointer types. However, an alternative reading would be that the allocator constructors themselves cannot throw. The change to the vector and string default constructors, making them unconditionally noexcept depends on this alternative reading.
I believe that the wording in the standard is not intended to forbid throwing default constructors for allocators. Indeed, I believe that allocators do not require default constructors and that if they provide a default constructor they should be allowed to throw. In addition, the noexcept specifications for the string and vector default constructors should be changed to make them conditional.[2015-01-18 Library reflector vote]
The issue has been identified as Tentatively Ready based on six votes in favour.
Proposed resolution:
Change 17.6.3.5 [allocator.requirements] p4 as indicated:
An allocator type X shall satisfy the requirements of CopyConstructible (17.6.3.1). The X::pointer, X::const_pointer, X::void_pointer, and X::const_void_pointer types shall satisfy the requirements of NullablePointer (17.6.3.3). No constructor, comparison operator, copy operation, move operation, or swap operation on these pointer types shall exit via an exception. X::pointer and X::const_pointer shall also satisfy the requirements for a random access iterator (24.2).
Change 21.4 [basic.string] following p5, class template basic_string synopsis, as indicated: (This change assumes that N4258 has been applied, as voted on in Urbana on 2014-11-08)
// 21.4.2, construct/copy/destroy: basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { }
An alternative formulation of the above would be:
// 21.4.2, construct/copy/destroy: basic_string() noexcept(is_nothrow_default_constructible<Allocator>{}) : basic_string(Allocator()) { }
Change 23.3.6.1 [vector.overview] following p2, class template vector synopsis, as indicated: (This change assumes that N4258 has been applied, as voted on in Urbana on 2014-11-08)
// 23.3.6.2, construct/copy/destroy: vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { }
An alternative formulation of the above would be:
// 23.3.6.2, construct/copy/destroy: vector() noexcept(is_nothrow_default_constructible<Allocator>{}) : vector(Allocator()) { }
Section: 18.6 [support.dynamic], 18.6.1.1 [new.delete.single], 18.6.1.2 [new.delete.array] Status: Tentatively Ready Submitter: Richard Smith Opened: 2014-11-23 Last modified: 2015-04-08
View all issues with Tentatively Ready status.
Discussion:
N3778 added the following sized deallocation signatures to the library:
void operator delete(void* ptr, std::size_t size) noexcept; void operator delete[](void* ptr, std::size_t size) noexcept; void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept; void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept;
The former two are an essential part of the proposal. The latter two seem spurious — they are not called when new (std::nothrow) X fails due to X::X() throwing, because the core language rules for selecting a placement deallocation function do not consider passing a size argument. Instead, the above would be the matching deallocation functions for:
void *operator new(std::size_t size, std::size_t size_again, const std::nothrow_t&) noexcept; void *operator new[](std::size_t size, std::size_t size_again, const std::nothrow_t&) noexcept;
... which don't exist.
Since they're not implicitly called, the only other possible use for those functions would be to perform an explicitly non-throwing deallocation. But... the first two overloads are already explicitly non-throwing and are required to be semantically identical to the second two. So there's no point in making an explicit call to the second pair of functions either. It seems to me that we should remove the (void*, size_t, nothrow_t) overloads, because the core working group decided during the Urbana 2014 meeting, that no change to the core language was warranted.[2014-11-23, Daniel suggests concrete wording changes]
[2015-02 Cologne]
Nobody can call those overloads, since the nothrow allocation functions cannot throw. JY: Ship it. GR: Should we do due diligence and make sure we're deleting what we mean to be deleting? [Some checking, everything looks good.]
Accepted.Proposed resolution:
This wording is relative to N4140.
Change 18.6 [support.dynamic], header <new> synopsis, as indicated:
[…] void operator delete(void* ptr, std::size_t size) noexcept;void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…] void operator delete[](void* ptr, std::size_t size) noexcept;void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…]
Change 18.6.1.1 [new.delete.single], starting before p19, as indicated:
void operator delete(void* ptr, const std::nothrow_t&) noexcept;void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…]
-20- Replaceable: a C++ program may define a function with signature void operator delete(void* ptr, const std::nothrow_t&) noexcept that displaces the default version defined by the C++ standard library.If this function (without size parameter) is defined, the program should also define void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept. If this function with size parameter is defined, the program shall also define the version without the size parameter. [Note: The default behavior below may change in the future, which will require replacing both deallocation functions when replacing the allocation function. — end note][…]-22- Requires: If present, the std::size_t size argument must equal the size argument passed to the allocation function that returned ptr.-23- Required behavior: Calls to operator delete(void* ptr, std::size_t size, const std::nothrow_t&) may be changed to calls to operator delete(void* ptr, const std::nothrow_t&) without affecting memory allocation. [Note: A conforming implementation is for operator delete(void* ptr, std::size_t size, const std::nothrow_t&) to simply call operator delete(void* ptr, const std::nothrow_t&). — end note]-24- Default behavior:operator delete(void* ptr, std::size_t size, const std::nothrow_t&) calls operator delete(ptr, std::nothrow), andoperator delete(void* ptr, const std::nothrow_t&) calls operator delete(ptr).
Change 18.6.1.2 [new.delete.array], starting before p16, as indicated:
void operator delete[](void* ptr, const std::nothrow_t&) noexcept;void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…]
-17- Replaceable: a C++ program may define a function with signature void operator delete[](void* ptr, const std::nothrow_t&) noexcept that displaces the default version defined by the C++ standard library.If this function (without size parameter) is defined, the program should also define void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept. If this function with size parameter is defined, the program shall also define the version without the size parameter. [Note: The default behavior below may change in the future, which will require replacing both deallocation functions when replacing the allocation function. — end note][…]-19- Requires: If present, the std::size_t size argument must equal the size argument passed to the allocation function that returned ptr.-20- Required behavior: Calls to operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) may be changed to calls to operator delete[](void* ptr, const std::nothrow_t&) without affecting memory allocation. [Note: A conforming implementation is for operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) to simply call operator delete[](void* ptr, const std::nothrow_t&). — end note]-21- Default behavior:operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) calls operator delete[](ptr, std::nothrow), andoperator delete[](void* ptr, const std::nothrow_t&) calls operator delete[](ptr).
Section: 26.4.7 [complex.value.ops] Status: Tentatively Ready Submitter: Marshall Clow Opened: 2014-10-22 Last modified: 2015-04-08
View all other issues in [complex.value.ops].
View all issues with Tentatively Ready status.
Discussion:
Different implementations give different answers for the following code:
#include <iostream> #include <complex> int main () { std::cout << std::polar(-1.0, -1.0) << '\n'; return 0; }
One implementation prints:
(nan, nan)
Another:
(-0.243068, 0.243068)
Which is correct? Or neither?
In this list, Howard Hinnant wrote:I've read this over several times. I've consulted C++11, C11, and IEC 10967-3. [snip]
I'm finding:
The magnitude of a complex number == abs(c) == hypot(c.real(), c.imag()) and is always non-negative (by all three of the above standards).
Therefore no complex number exists for which abs(c) < 0.
Therefore when the first argument to std::polar (which is called rho) is negative, no complex number can be formed which meets the post-conidtion that abs(c) == rho.
One could argue that this is already covered in 26.4 [complex.numbers]/3, but I think it's worth making explicit.
[2015-02, Cologne]
Discussion on whether theta should also be constrained.
TK: infinite theta doesn't make sense, whereas infinite rho does (theta is on a compact domain, rho is on a non-compact domain).
AM: We already have a narrow contract, so I don't mind adding further requirements. Any objections to requiring that theta be finite?
Some more discussion, but general consensus. Agreement that if someone finds the restrictions problematic, they should write
a proper paper to address how std::polar should behave. For now, we allow infinite rho (but not NaN and not negative),
and require finite theta.
Proposed resolution:
This wording is relative to N4296.
Change 26.4.7 [complex.value.ops] around p9 as indicated
template<class T> complex<T> polar(const T& rho, const T& theta = 0);-?- Requires: rho shall be non-negative and non-NaN. theta shall be finite.
-9- Returns: The complex value corresponding to a complex number whose magnitude is rho and whose phase angle is theta.
Section: X [alg.random.sample] Status: Tentatively Ready Submitter: Joe Gottman Opened: 2014-12-17 Last modified: 2015-04-08
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts
According to paragraph 10.1 of the Library Fundamentals 1 draft, the complexity of the new std::experimental::sample template function is O(n). Note that n is actually a parameter of this function, corresponding to the sample size. But both common algorithms for sampling, the selection algorithm and the reservoir algorithm, are linear with respect to the population size, which is often many orders of magnitude bigger than the sample size.
[2015-02, Cologne]
AM: I suggest we make this a DR against the Fundamentals TS.
GR: Agreed, this is a no-brainer.
Proposed resolution:
This wording is relative to N4335 in regard to fundamental-ts changes.
Change X [alg.random.sample] p5 to read:
-5- Complexity: O(
nlast - first).
Section: 17.6.3.5 [allocator.requirements], 20.7.8.1 [allocator.traits.types] Status: Tentatively Ready Submitter: Howard Hinnant Opened: 2015-01-18 Last modified: 2015-04-08
View other active issues in [allocator.requirements].
View all other issues in [allocator.requirements].
View all issues with Tentatively Ready status.
Discussion:
Table 28 — "Allocator requirements" says that X::is_always_equal has a default value of is_empty<X>, and this is consistent with the return type description:
Identical to or derived from true_type or false_type
is_empty<X> is guaranteed to be derived from either true_type or false_type. So far so good.
20.7.8.1 [allocator.traits.types]/p10 says:typedef see below is_always_equal;Type: Alloc::is_always_equal if the qualified-id Alloc::is_always_equal is valid and denotes a type (14.8.2); otherwise is_empty<Alloc>::type.
This is subtly different than what Table 28 says is the default: is_empty<Alloc>::type is not is_empty<Alloc>, but is rather one of true_type or false_type.
There are two ways to fix this:Change Table 28 to say: is_empty<X>::type.
orChange 20.7.8.1 [allocator.traits.types]/p10:
Type: Alloc::is_always_equal if the qualified-id Alloc::is_always_equal is valid and denotes a type (14.8.2); otherwise is_empty<Alloc>
::type.
Both options are correct, and I see no reason to prefer one fix over the other. But Table 28 and 20.7.8.1 [allocator.traits.types]/p10 should be consistent with one another.
[2015-02 Cologne]
DK: We should accept the first bullet. GR: Why does is_empty even have a type member? AM: All type traits have a type member. I agree with DK's preference for the first type.
Proposed resolution:
This wording is relative to N4296.
Change 17.6.3.5 [allocator.requirements], Table 28 — "Allocator requirements" as presented:
Table 28 — Allocator requirements Expression Return type Assertion/note
pre-/post-conditionDefault … X::is_always_equal Identical to or derived
from true_type or
false_type[…] is_empty<X>::type …
Section: 17.6.3.5 [allocator.requirements] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2015-03-22 Last modified: 2015-04-08
View other active issues in [allocator.requirements].
View all other issues in [allocator.requirements].
View all issues with Tentatively Ready status.
Discussion:
This issue is a spin-off of issue LWG 2447: It focuses on the observation that 17.6.3.5 [allocator.requirements] p9 (based on the numbering of working draft N4296) gives the template member construct more relaxations than the template member destroy:
An allocator may constrain the types on which it can be instantiated and the arguments for which its construct member may be called. If a type cannot be used with a particular allocator, the allocator class or the call to construct may fail to instantiate.
Construction and destruction of a type T are usually intimately related to each other, so it seems similarly useful to allow the destroy member to fail to instantiate for a possible sub-set of instantiation types.
[2015-04-01 Library reflector vote]
The issue has been identified as Tentatively Ready based on six votes in favour.
Proposed resolution:
This wording is relative to N4296.
Change 17.6.3.5 [allocator.requirements] p9 as indicated:
-8- An allocator may constrain the types on which it can be instantiated and the arguments for which its construct or destroy members may be called. If a type cannot be used with a particular allocator, the allocator class or the call to construct or destroy may fail to instantiate.
Section: 21.8 [c.strings] Status: Tentatively Ready Submitter: S. B.Tam Opened: 2015-01-18 Last modified: 2015-04-08
View other active issues in [c.strings].
View all other issues in [c.strings].
View all issues with Tentatively Ready status.
Discussion:
N4296 Table 73 mentions the functions mbsrtowc and wcsrtomb, which are not defined in ISO C or ISO C++. Presumably they should be mbsrtowcs and wcsrtombs instead.
[2015-04-02 Library reflector vote]
The issue has been identified as Tentatively Ready based on six votes in favour.
Proposed resolution:
This wording is relative to N4296.
Table 33 — Potential mbstate_t data races mbrlen mbrtowc mbsrtowcs mbtowc wcrtomb wcsrtombs wctomb