Revised 2015-09-28 at 05:09:24 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: 17.6.4.10 [res.on.objects] Status: Tentatively Ready Submitter: Geoffrey Romer Opened: 2012-12-17 Last modified: 2015-05-05
View all other issues in [res.on.objects].
View all issues with Tentatively Ready status.
Discussion:
The standard currently does not discuss when library objects may be accessed, except in a non-normative note pertaining to synchronization in [res.on.objects], leaving it ambiguous whether single-threaded code can access a library object during its construction or destruction. For example, there is a reasonable question as to what happens if the deleter supplied to a unique_ptr transitively accesses the unique_ptr itself during unique_ptr's destruction; a straightforward reading suggests that this is permitted, and that the deleter will see the unique_ptr still holding the originally stored pointer, but consensus on the LWG reflector indicates this was not the intent (see discussion beginning with c++std-lib-33362).
[2013-03-15 Issues Teleconference]
Moved to Open.
Geoffrey will provide an example that clearly highlights the issue.
[2013-03-19 Geoffrey provides revised resolution and an example]
I contend that the most straightforward reading of the current standard requires the following example code to print "good" (because ~unique_ptr is not specified to modify the state of the internal pointer), but the consensus on the reflector was that its behavior should be undefined.
This example also shows that, contrary to a comment in the telecon, the PR is not tautological. 12.7 [class.cdtor]/p4 explicitly permits member function calls during destruction, so the behavior of this code is well-defined as far as the core language is concerned, despite the fact that it accesses a library object after the end of the object's lifetime. If we want this code to have undefined behavior, we need to specify that at the library level.#include <memory> #include <iostream> class A; struct B { std::unique_ptr<A> a; }; struct A { B* b; ~A() { if (b->a.get() == this) { std::cout << "good" << std::endl; } } }; int main() { B b; b.a.reset(new A); b.a->b = &b; }
Previous resolution:
Change the title of sub-clause 17.6.4.10 [res.on.objects] as indicated:
Shared objects and the libraryLibrary object access [res.on.objects]Edit 17.6.4.10 [res.on.objects] p2 as indicated:
-2-
[Note: In particular, the program is required to ensure that completion of the constructor of any object of a class type defined in the standard library happens before any other member function invocation on that object and, unless otherwise specified, to ensure that completion of any member function invocation other than destruction on such an object happens before destruction of that object. This applies even to objects such as mutexes intended for thread synchronization. — end note]If an object of a standard library type is accessed outside of the object's lifetime (3.8 [basic.life]), the behavior is undefined unless otherwise specified.
[2014 Urbana]
STL: is this resolved by our change to the reeentrancy rules? [LWG 2414]
GR: don't think that solves the multi-threaded case
MC: I like changing the note to normative text
GR: uses the magic "happens before" words, and "access" is magic too
JW: I like this. strict improvement, uses the right wording we have to say this properly
STL: I like the last sentence of the note, could we add that as a new note at the end?
So add "[Note: This applies even to objects such as mutexes intended for thread synchronization.]" to the end and move to Ready
Proposed resolution:
This wording is relative to N3485.
Change the title of sub-clause 17.6.4.10 [res.on.objects] as indicated:
Shared objects and the libraryLibrary object access [res.on.objects]
Edit 17.6.4.10 [res.on.objects] p2 as indicated: [Editorial remark: The motivation, is to be more precise about the meaning of "outside the object's lifetime" in the presence of threads — end editorial remark]
-2- [Note: In particular, the program is required to ensure that completion of the constructor
of any object of a class type defined in the standard library happens before any other member function
invocation on that object and, unless otherwise specified, to ensure that completion of any member function
invocation other than destruction on such an object happens before destruction of that object. This applies
even to objects such as mutexes intended for thread synchronization. — end note]
If an object of a standard library type is accessed, and the beginning of the object's lifetime
(3.8 [basic.life]) does not happen before the access, or the access does not happen before the end
of the object's lifetime, the behavior is undefined unless otherwise specified. [Note: This applies even to
objects such as mutexes intended for thread synchronization. — end note]
Section: 19.3 [assertions] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2013-01-12 Last modified: 2015-09-27
View other active issues in [assertions].
View all other issues in [assertions].
View all issues with Tentatively Ready status.
Discussion:
It is unclear from the current specification whether assert() expressions can be used in (potential) constant expressions. As an example consider the implementation of a constexpr function:
#include <cassert> template<class T, unsigned N> struct array { T data[N]; constexpr const T& operator[](unsigned i) const { return assert(i < N), data[i]; } }; int main() { constexpr array<int, 3> ai = {1, 2, 3}; constexpr int i = ai[0]; int j = ai[0]; // constexpr int k = ai[5]; }
The first question is whether this program is guaranteed well-formed? A second question is whether is would guaranteed to be ill-formed, if we uncomment the last code line in main()?
The wording in 19.3 [assertions] doesn't add anything significant to the C99 wording. From the C99 specification (7.2 p1 and 7.2.1.1 p2) we get already some valuable guarantees:
The expression assert(e) is a void expression for all expressions e independent of the definition of NDEBUG.
If NDEBUG is defined, assert(e) is equivalent to the expression void() (or anything that cannot be distinguished from that).
The current wording does not yet guarantee that assert expressions can be used in constant expressions, but all tested implementations (gcc, MSVC) would already support this use-case. It seems to me that this should be possible without giving assert a special meaning for the core language.
As a related comment it should be added, that there is a core language proposal that intents to relax some current constraints for constexpr functions and literal types. The most interesting one (making void a literal types and allowing for expression-statements) would simplify the motivating example implementation of operator[] to:constexpr const T& operator[](unsigned i) const { assert(i < N); return data[i]; };
[2013-03-15 Issues Teleconference]
Moved to Open.
We are still gaining experience with constexpr as a language feature, and there may be work in Evolution that would help address some of these concerns. Defer discussion until we have a group familiar with any evolutionary direction.
[2014-06-08, Daniel comments and suggests wording]
After approval of N3652, void is now a literal type and constexpr functions can contain multiple statements, so this makes the guarantee that assert expressions are per-se constexpr-friendly even more relevant. A possible wording form could be along the lines of:
For every core constant expression e of scalar type that evaluates to true after being contextually converted to bool, the expression assert(e) shall be a prvalue core constant expression of type void.
Richard Smith pointed out some weaknesses of this wording form, for example it would not guarantee to require the following example to work:
constexpr void check(bool b) { assert(b); }
because b is not a core constant expression in this context.
He suggested improvements that lead to the wording form presented below (any defects mine).[Lenexa 2015-05-05]
MC : ran into this
Z : Is it guaranteed to be an expression?
MC : clarifies that assert runs at runtime, not sure what it does at compile time
STL : c standard guarantees its an expression and not a whole statement, so comma chaining it is ok
HH : Some implementations work as author wants it to
STL : also doing this as constexpr
DK/STL : discussing how this can actually work
HH : GCC 5 also implements it. We have implementor convergence
MC : Wants to do this without giving assert a special meaning
STL : NDEBUG being defined where assert appears is not how assert works. This is bug in wording. Should be "when assert is defined" or something like that. ... is a constant subexpression if NDEBUG is defined at the point where assert is last defined or redefined."
Would like to strike the "either" because ok if both debug or assertion is true. We want inclusive-or here
MC : is redefined needed?
STL : my mental model is its defined once and then redefined
HH : wants to up to P2
Z/STL : discussing how wording takes care of how/when assert is defined/redefefined
STL/WB : discussing whether to move to ready or review. -> Want to move it to ready.
ask for updated wording
p3 -> p2
plan to go to ready after checking wording
[Telecom 2015-06-30]
HH: standardizing existing practice
MC: what about the comment from Lenexa about striking "either"?
HH: all three implementations accept it
MC: update issue to strike "either" and move to Tentatively Ready
Proposed resolution:
This wording is relative to N3936.
Previous resolution [SUPERSEDED]:
Introduce the following new definition to the existing list in 17.3 [definitions]: [Drafting note: If LWG 2296 is accepted before this issue, the accepted wording for the new definition should be used instead — end drafting note]
constant subexpression [defns.const.subexpr]
an expression whose evaluation as subexpression of a conditional-expression CE (5.16 [expr.cond]) would not prevent CE from being a core constant expression (5.20 [expr.const]).Insert a new paragraph following 19.3 [assertions] p1 as indicated:
-?- An expression assert(E) is a constant subexpression ( [defns.const.subexpr]), if either
NDEBUG is defined at the point where assert(E) appears, or
E contextually converted to bool (4 [conv]), is a constant subexpression that evaluates to the value true.
Introduce the following new definition to the existing list in 17.3 [definitions]: [Drafting note: If LWG 2296 is accepted before this issue, the accepted wording for the new definition should be used instead — end drafting note]
constant subexpression [defns.const.subexpr]
an expression whose evaluation as subexpression of a conditional-expression CE (5.16 [expr.cond]) would not prevent CE from being a core constant expression (5.20 [expr.const]).
Insert a new paragraph following 19.3 [assertions] p1 as indicated:
-?- An expression assert(E) is a constant subexpression ( [defns.const.subexpr]), if
NDEBUG is defined at the point where assert(E) appears, or
E contextually converted to bool (4 [conv]), is a constant subexpression that evaluates to the value true.
Section: 28.11.2 [re.alg.match] Status: Tentatively Ready Submitter: Howard Hinnant Opened: 2013-07-14 Last modified: 2015-09-14
View all other issues in [re.alg.match].
View all issues with Tentatively Ready status.
Discussion:
28.11.2 [re.alg.match] p2 in describing regex_match says:
-2- Effects: Determines whether there is a match between the regular expression e, and all of the character sequence [first,last). The parameter flags is used to control how the expression is matched against the character sequence. Returns true if such a match exists, false otherwise.
It has come to my attention that different people are interpreting the first sentence of p2 in different ways:
If a search of the input string using the regular expression e matches the entire input string, regex_match should return true.
Search the input string using the regular expression e. Reject all matches that do not match the entire input string. If a such a match is found, return true.
The difference between these two subtly different interpretations is found using the following ECMAScript example:
std::regex re("Get|GetValue");
Using regex_search, this re can never match the input string "GetValue", because ECMA specifies that alternations are ordered, not greedy. As soon as "Get" is matched in the left alternation, the matching algorithm stops.
Using definition 1, regex_match would return false for an input string of "GetValue". However definition 2 alters the grammar and appears equivalent to augmenting the regex with a trailing '$', which is an anchor that specifies, reject any matches which do not come at the end of the input sequence. So, using definition 2, regex_match would return true for an input string of "GetValue". My opinion is that it would be strange to have regex_match return true for a string/regex pair that regex_search could never find. I.e. I favor definition 1. John Maddock writes: The intention was always that regex_match would reject any match candidate which didn't match the entire input string. So it would find GetValue in this case because the "Get" alternative had already been rejected as not matching. Note that the comparison with ECMA script is somewhat moot, as ECMAScript defines the regex grammar (the bit we've imported), it does not define anything like regex_match, nor do we import from ECMAScript the behaviour of that function. So IMO the function should behave consistently regardless of the regex dialect chosen. Saying "use awk regexes" doesn't cut it, because that changes the grammar in other ways. (John favors definition 2). We need to clarify 28.11.2 [re.alg.match]/p2 in one of these two directions.[2014-06-21, Rapperswil]
AM: I think there's a clear direction and consensus we agree with John Maddock's position, and if noone else thinks we need the other function I won't ask for it.
Marshall Clow and STL to draft.[2015-06-10, Marshall suggests concrete wording]
[2015-01-11, Telecom]
Move to Tenatatively Ready
Proposed resolution:
This wording is relative to N4527.
Change 28.11.2 [re.alg.match]/2, as follows:
template <class BidirectionalIterator, class Allocator, class charT, class traits> bool regex_match(BidirectionalIterator first, BidirectionalIterator last, match_results<BidirectionalIterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);-1- Requires: The type BidirectionalIterator shall satisfy the requirements of a Bidirectional Iterator (24.2.6).
-2- Effects: Determines whether there is a match between the regular expression e, and all of the character sequence [first,last). The parameter flags is used to control how the expression is matched against the character sequence. When determining if there is a match, only potential matches that match the entire character sequence are considered. Returns true if such a match exists, false otherwise. [Example:std::regex re("Get|GetValue"); std::cmatch m; regex_search("GetValue", m, re); // returns true, and m[0] contains "Get" regex_match ("GetValue", m, re); // returns true, and m[0] contains "GetValue" regex_search("GetValues", m, re); // returns true, and m[0] contains "Get" regex_match ("GetValues", m, re); // returns false— end example]
[…]
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 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: 20.8.2.2.1 [util.smartptr.shared.const] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2015-05-05 Last modified: 2015-08-03
View all other issues in [util.smartptr.shared.const].
View all issues with Tentatively Ready status.
Discussion:
20.8.2.2.1 [util.smartptr.shared.const] includes several "Exception safety" elements, but that is not one of the elements defined in 17.5.1.4 17.5.1.4 [structure.specifications]. We should either define what it means, or just move those sentences into the Effects: clause.
[2015-06, Telecom]
Move to Tentatively Ready.
Proposed resolution:
This wording is relative to N4431.
Change 20.8.2.2.1 [util.smartptr.shared.const] as follows:
template<class Y> explicit shared_ptr(Y* p);[…]
-4- Effects: Constructs a shared_ptr object that owns the pointer p. If an exception is thrown, delete p is called. […]-7- Exception safety: If an exception is thrown, delete p is called.template <class Y, class D> shared_ptr(Y* p, D d); template <class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a);[…][…]
-9- Effects: Constructs a shared_ptr object that owns the object p and the deleter d. The second and fourth constructors shall use a copy of a to allocate memory for internal use. If an exception is thrown, d(p) is called. […]-12- Exception safety: If an exception is thrown, d(p) is called.template <class Y> explicit shared_ptr(const weak_ptr<Y>& r);[…]
-24- Effects: Constructs a shared_ptr object that shares ownership with r and stores a copy of the pointer stored in r. If an exception is thrown, the constructor has no effect. […]-27- Exception safety: If an exception is thrown, the constructor has no effect.template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);[…]
-29- 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())). If an exception is thrown, the constructor has no effect.-30- Exception safety: If an exception is thrown, the constructor has no effect.
Section: X [memory.smartptr.shared.obs] Status: Tentatively Ready Submitter: Jeffrey Yasskin Opened: 2015-05-11 Last modified: 2015-09-14
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts.v2
S. B. Tam reported this here.
N3920 changed operator*() in [util.smartptr.shared.obs] as:Remarks: When T is an array type or cv-qualified void, it is unspecified whether this member function is declared. …
This excludes cv-unqualified void, which is probably unintended.
[2015-09-11, Telecom]
Move to Tentatively Ready
Proposed resolution:
In the library fundamentals v2, [memory.smartptr.shared.obs] p2, change as indicated:
Remarks: When T is an array type or (possibly cv-qualified) 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.
Section: 18.6 [support.dynamic], 20.2 [utility], 20.3.5 [pair.piecewise], 20.7.2 [memory.syn], 20.7.6 [allocator.tag], 30.4 [thread.mutex] Status: Tentatively Ready Submitter: Ville Voutilainen Opened: 2015-06-13 Last modified: 2015-08-03
View all other issues in [support.dynamic].
View all issues with Tentatively Ready status.
Discussion:
std::experimental::optional, for certain reasons, specifies its nullopt type to not be DefaultConstructible. It doesn't do so for its tag type in_place_t and neither does the standard proper for any of its tag types. That turns out to be very unfortunate, consider the following:
#include <memory> #include <array> void f(std::array<int, 1>, int) {} // #1 void f(std::allocator_arg_t, int) {} // #2 int main() { f({}, 666); // #3 }
The call at #3 is ambiguous. What's even worse is that if the overload #1 is removed, the call works just fine. The whole point of a tag type is that it either needs to mentioned in a call or it needs to be a forwarded argument, so being able to construct a tag type like that makes no sense.
Making the types have an explicit default constructor might have helped, but CWG 1518 is going against that idea. [optional.nullopt]/3 solves this problem for nullopt:Type nullopt_t shall not have a default constructor. It shall be a literal type. Constant nullopt shall be initialized with an argument of literal type.
[2015-06, Telecom]
Move to Tentatively Ready.
Proposed resolution:
This wording is relative to N4527.
In 18.6 [support.dynamic]/1, change the header <new> synopsis:
[…] struct nothrow_t{}; see below extern const nothrow_t nothrow; […]
Add a new paragraph after 18.6 [support.dynamic]/1 (following the header <new> synopsis):
-?- Type nothrow_t shall not have a default constructor.
In 20.2 [utility]/2, change the header <utility> synopsis:
[…] // 20.3.5, pair piecewise construction struct piecewise_construct_t{ }; see below constexpr piecewise_construct_t piecewise_construct{ unspecified }; […]
Add a new paragraph after 20.2 [utility]/2 (following the header <utility> synopsis):
-?- Type piecewise_construct_t shall not have a default constructor. It shall be a literal type. Constant piecewise_construct shall be initialized with an argument of literal type.
In 20.3.5 [pair.piecewise], apply the following edits:
struct piecewise_construct_t{ }; constexpr piecewise_construct_t piecewise_construct{ unspecified };
In 20.7.2 [memory.syn]/1, change the header <memory> synopsis:
[…] // 20.7.6, allocator argument tag struct allocator_arg_t{ }; see below constexpr allocator_arg_t allocator_arg{ unspecified }; […]
Add a new paragraph after 20.7.2 [memory.syn]/1 (following the header <memory> synopsis):
-?- Type allocator_arg_t shall not have a default constructor. It shall be a literal type. Constant allocator_arg shall be initialized with an argument of literal type.
In 20.7.6 [allocator.tag], apply the following edits:
namespace std { struct allocator_arg_t{ }; constexpr allocator_arg_t allocator_arg{ unspecified }; }
Editorial drive-by: piecewise_construct_t is written, in 20.3.5 [pair.piecewise] like
struct piecewise_construct_t { }; constexpr piecewise_construct_t piecewise_construct{};whereas other tag types such as allocator_construct_t are, in e.g. 20.7.6 [allocator.tag], written like
namespace std { struct allocator_arg_t { }; constexpr allocator_arg_t allocator_arg{}; }We should decide whether or not to write out the std namespace in such paragraphs. I would suggest not to write it out.
In 30.4 [thread.mutex]/1, change the header <mutex> synopsis:
[…] struct defer_lock_t{ }; see below struct try_to_lock_t{ }; see below struct adopt_lock_t{ }; see below constexpr defer_lock_t defer_lock { unspecified }; constexpr try_to_lock_t try_to_lock { unspecified }; constexpr adopt_lock_t adopt_lock { unspecified }; […]
Add three new paragraphs after [thread.mutex]/1 (following the header <mutex> synopsis):
-?- Type defer_lock_t shall not have a default constructor. It shall be a literal type. Constant defer_lock shall be initialized with an argument of literal type.
-?- Type try_to_lock_t shall not have a default constructor. It shall be a literal type. Constant try_to_lock shall be initialized with an argument of literal type. -?- Type adopt_lock_t shall not have a default constructor. It shall be a literal type. Constant adopt_lock shall be initialized with an argument of literal type.
Section: X [memory.observer.ptr.special] Status: Tentatively Ready Submitter: Tim Song Opened: 2015-07-07 Last modified: 2015-08-03
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts.v2
In N4529 [memory.observer.ptr.special] paragraphs 15, 17 and 19, the >, <= and >= operators of observer_ptr are shown as
template <class W> bool operator>(observer_ptr<W> p1, observer_ptr<W> p2);
whereas in [header.memory.synop] they are shown as
template <class W1, class W2> bool operator>(observer_ptr<W1> p1, observer_ptr<W2> p2);
Given that the specification of operator< took special care to support hetergeneous types, presumably the second version is intended.
[2015-07, Telecom]
Move to Tentatively Ready.
Proposed resolution:
This wording is relative to N4529.
Edit X [memory.observer.ptr.special] as indicated:
-15- template <class W1, class W2> bool operator>(observer_ptr<W1> p1, observer_ptr<W2> p2);[…]
-17- template <class W1, class W2> bool operator<=(observer_ptr<W1> p1, observer_ptr<W2> p2);[…]
-19- template <class W1, class W2> bool operator>=(observer_ptr<W1> p1, observer_ptr<W2> p2);
Section: X [propagate_const.assignment] Status: Tentatively Ready Submitter: Tim Song Opened: 2015-07-08 Last modified: 2015-08-03
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts.v2
N4529 [propagate_const.assignment] depicts the two operator=s described as returning by value. This is obviously incorrect. The class synopsis correctly shows them as returning by reference.
[2015-06, Telecom]
Move to Tentatively Ready.
Proposed resolution:
This wording is relative to N4529.
Edit [propagate_const.assignment] as indicated:
-1- template <class U> constexpr propagate_const& operator=(propagate_const<U>&& pu)[…]
-5- template <class U> constexpr propagate_const& operator=(U&& u)
Section: 20.9.12.2.2 [func.wrap.func.mod] Status: Tentatively Ready Submitter: Tim Song Opened: 2015-08-04 Last modified: 2015-09-14
View all other issues in [func.wrap.func.mod].
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts
20.9.12.2.2 [func.wrap.func.mod] says that the precondition of swap is
this->get_memory_resource() == other->get_memory_resource()
That compares two pointers and so requires the memory resource used by *this and other to be the exact same object. That doesn't seem correct (for one, it would essentially outlaw swapping all functions constructed with "plain" allocators, since they would each have their own resource_adaptor object and so the pointers will not compare equal). Presumably the intent is to compare the memory_resources for equality.
Also, other is a reference, not a pointer.
[2015-09-11, Telecom]
Move to Tentatively Ready
Proposed resolution:
This wording is relative to N4480.
Edit 20.9.12.2.2 [func.wrap.func.mod] as indicated:
void swap(function& other);-2- Requires: *this->get_memory_resource() == *other
-3- Effects: Interchanges the targets of *this and other. -4- Remarks: The allocators of *this and other are not interchanged.->.get_memory_resource().