Revised 2015-11-16 at 02:11:21 UTC
Section: 23.2 [container.requirements] Status: Tentatively NAD Submitter: Paolo Carlini Opened: 2007-11-11 Last modified: 2015-04-08
Priority: 2
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: 26.8 [c.math] Status: Tentatively Ready Submitter: Daniel Krügler Opened: 2012-10-02 Last modified: 2015-11-04
Priority: 2
View other active issues in [c.math].
View all other issues in [c.math].
View all issues with Tentatively Ready status.
Discussion:
In C++03 the following two programs are invalid:
#include <cmath> int main() { std::abs(0u); }
#include <cstdlib> int main() { std::abs(0u); }
because none of the std::abs() overloads is a best match.
In C++11 the additional "sufficient overload" rule from 26.8 [c.math] p11 (see also LWG 2086) can be read to be applicable to the std::abs() overloads as well, which can lead to the following possible conclusions:
The program
#include <type_traits> #include <cmath> static_assert(std::is_same<decltype(std::abs(0u)), double>(), "Oops"); int main() { std::abs(0u); // Calls std::abs(double) }
is required to be well-formed, because of sub-bullet 2 ("[..] or an integer type [..]") of 26.8 [c.math] p11 (Note that the current resolution of LWG 2086 doesn't fix this problem).
Any translation unit including both <cmath> and <cstdlib> might be ill-formed because of two conflicting requirements for the return type of the overload std::abs(int).
It seems to me that at least the second outcome is not intended, personally I think that both are unfortunate: In contrast to all other floating-point functions explicitly listed in sub-clause 26.8 [c.math], the abs overloads have a special and well-defined meaning for signed integers and thus have explicit overloads returning a signed integral type. I also believe that there is no problem accepting that std::fabs(0u) is well-defined with return type double, because the leading 'f' clearly signals that we have a floating point function here. But the expected return type of std::abs(0u) seems less than clear to me. A very reasonable answer could be that this has the same type as its argument type, alternatively it could be a reasonably chosen signed integer type, or a floating point type. It should also be noted, that the corresponding "generic type function" rule set from C99/C1x in 7.25 p2+3 is restricted to the floating-point functions from <math.h> and <complex.h>, so cannot be applied to the abs functions (but to the fabs functions!).
Selecting a signed integer return type for unsigned input values can also problematic: The directly corresponding signed integer type would give half of the possible argument values an implementation-defined result value. Choosing the first signed integer value that can represent all positive values would solve this problem for unsigned int, but there would be no clear answer for the input type std::uintmax_t.Based on this it seems to me that the C++03 state in regard to unsigned integer values was the better situation, alerting the user that this code is ambigious at the moment (This might be change with different core-language rules as described in N3387).
[2013-04-20, Bristol]
Resolution: leave as new and bring it back in Chicago.
[2013-09 Chicago]
This issue also relates to LWG 2294
STL: these two issues should be bundled Stefanus: do what Pete says, and add overloads for unsigned to return directly STL: agree Consensus that this is an issue Walter: motion to move to Open STL: no wording for 2294 Stefanus: move to open and note the 2 issues are related and should be moved together Stefanus: add and define unsigned versions of abs()[2014-02-03 Howard comments]
Defining abs() for unsigned integers is a bad idea. Doing so would turn compile time errors into run time errors, especially in C++ where we have templates, and the types involved are not always apparent to the programmer at design time. For example, consider:
template <class Int>
Int
analyze(Int x, Int y)
{
// ...
if (std::abs(x - y) < threshold)
{
// ...
}
// ...
}
std::abs(expr) is often used to ask: Are these two numbers sufficiently close? When the assumption is that the two numbers are signed (either signed integral, or floating point), the logic is sound. But when the same logic is accidentally used with an arithmetic type not capable of representing negative numbers, and especially if unsigned overflow will silently happen, then the logic is no longer correct:
auto i = analyze(20u, 21u); // Today a compile time error // But with abs(unsigned) becomes a run time error
This is not idle speculation. Search the net for "abs unsigned" here or here.
In C++11, chrono durations and time_points are allowed to be based on unsigned integers. Taking the absolute value of the difference of two such time_points would be easy to accidentally do (say in code templated on time_points), and would certainly be a logic bug, caught at compile time unless we provide the error prone abs(unsigned).[2015-02, Cologne]
GR: Do we want to make the changes to both <cmath> and <cstdlib>?
AM: I think so; we should provide consistent overloads.
GR: Then we're imposing restrictions on what users put in the global namespace.
AM: I'm not so worried about that. Users already know not to use C library names.
VV: So what are we going to do about unsigned integers? AM: We will say that they are ill-formed.
AM: Does anyone volunteer to send updated wording to Daniel? GR, can you do it? GR: Sure.
GR: To clarify: we want to make unsigned types ill-formed?
AM: With promotion rank at least unsigned int.
GR: And NL suggests to just list those types.
This wording is relative to N3376.
Change 26.8 [c.math] p11 as indicated:
-11- Moreover, except for the abs functions, there shall be additional overloads sufficient to ensure:
[…]
[2015-03-03, Geoffrey Romer provides improved wording]
In the following I've drafted combined wording to resolve LWG 2192 and 2294. Note that the first two paragraphs are taken verbatim from the P/R of LWG 2294, but the third is newly drafted:
[2015-05-05 Lenexa: Howard to draft updated wording]
[2015-09-11: Howard updated wording]
[2015-10, Kona Saturday afternoon]
HH: abs() for unsigned types is really dangerous. People often use abs(x - y), which would be a disaster.
TK: That's why you need a two-argument abs_diff(x, y), especially for unsigned types.
JW: Lawrence has a proposal for abs_diff in the mailing.
STL: As an alternative to considering promotions, I would just ban all unsigned types, even unsigned char.
STL: Does the PR change any implementation? Is the final paragraph just a consequence?
HH: It's a consequence. It could just be a note.
VV: Ship it as is.
STL: Editorial: capitalize the first letter in the Note.
Move to Tentatively ready.
Proposed resolution:
This wording is relative to N4527.
Insert the following new paragraphs after 26.8 [c.math] p7:
-6- In addition to the int versions of certain math functions in <cstdlib>, C++ adds long and long long overloaded versions of these functions, with the same semantics.
-7- The added signatures are:long abs(long); // labs() long long abs(long long); // llabs() ldiv_t div(long, long); // ldiv() lldiv_t div(long long, long long); // lldiv()-?- To avoid ambiguities, C++ also adds the following overloads of abs() to <cstdlib>, with the semantics defined in <cmath>:
float abs(float); double abs(double); long double abs(long double);-?- To avoid ambiguities, C++ also adds the following overloads of abs() to <cmath>, with the semantics defined in <cstdlib>:
int abs(int); long abs(long); long long abs(long long);-?- If abs() is called with an argument of type X for which is_unsigned<X>::value is true and if X cannot be converted to int by integral promotion (4.5 [conv.prom]), the program is ill-formed. [Note: arguments that can be promoted to int are permitted for compatibility with C. — end note]
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
Priority: 2
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.9.6 [comparisons] Status: Tentatively Ready Submitter: Joaquín M López Muñoz Opened: 2014-10-30 Last modified: 2015-11-04
Priority: 2
View other active issues in [comparisons].
View all other issues in [comparisons].
View all issues with Tentatively Ready status.
Discussion:
less<void>::operator(t, u) (and the same applies to the rest of void specializations for standard comparison function objects) returns t < u even if t and u are pointers, which by 5.9 [expr.rel]/3 is undefined except if both pointers point to the same array or object. This might be regarded as a specification defect since the intention of N3421 is that less<> can substitute for less<T> in any case where the latter is applicable. less<void> can be rewritten in the following manner to cope with pointers:
template<> struct less<void> { typedef unspecified is_transparent; template <class T, class U> struct pointer_overload : std::is_pointer<std::common_type_t<T, U>> {}; template < class T, class U, typename std::enable_if<!pointer_overload<T, U>::value>::type* = nullptr > auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) < std::forward<U>(u)) { return std::forward<T>(t) < std::forward<U>(u); } template < class T, class U, typename std::enable_if<pointer_overload<T, U>::value>::type* = nullptr > auto operator()(T&& t, U&& u) const -> decltype(std::declval<std::less<std::common_type_t<T, U>>>()(std::forward<T>(t), std::forward<U>(u))) { std::less<std::common_type_t<T, U>> l; return l(std::forward<T>(t), std::forward<U>(u)); } };
This wording is relative to N4140.
Change 20.9.6 [comparisons] p14 as indicated:
-14- For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not. For template specializations greater<void>, less<void>, greater_equal<void>, and less_equal<void>, the call operator with arguments whose common type CT is a pointer yields the same value as the corresponding comparison function object class specialization for CT.
[2015-02, Cologne]
AM: Is there any way this will be resolved elsewhere? VV: No. AM: Then we should bite the bullet and deal with it here.
MC: These diamond operators are already ugly. Making them more ugly isn't a big problem. JY found some issue with types that are convertible, and will reword. Jeffrey suggests improved wording.[2015-05, Lenexa]
STL: when diamond functions designed, this was on purpose
STL: this does go against the original design
STL: library is smarter and can give a total order
MC: given that the original design rejected this, give back to LEWG
STL: original proposal did not talk about total order
STL: don't feel strongly about changing the design
STL: no objections to taking this issue with some wording changes if people want it
MC: not happy with wording, comparing pointers — what does that mean?
STL: needs careful attention to wording
STL: want to guarantee that nullptr participates in total ordering
STL: all hooks into composite pointer type
MC: move from new to open with better wording
STL: to check updates to issue after Lenexa
[2015-06, Telecom]
MC: STL on the hook to update. He's shipping something today so not here.
MC: also add link to N4229
[2015-10, Kona Saturday afternoon]
STL was on the hook for wording, but STL: I don't care. The architecture on which this is an issue does not exist.
STL: We will also need to incorporate nullptr. TK: I think that's implied, since the wording is in terms of the resulting operation, not the deduced types.
STL: Seems legit. MC: I guess I'm OK with this. TK: I'm weakly in favour, so that we can get people to use transparent comparators without worrying.
STL: There's no change to implementations.
Move to Tentatively ready.
Proposed resolution:
This wording is relative to N4296.
Change 20.9.6 [comparisons] p14 as indicated:
-14- For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not. For template specializations greater<void>, less<void>, greater_equal<void>, and less_equal<void>, if the call operator calls a built-in operator comparing pointers, the call operator yields a total order.
Section: 20.8.1.3.1 [unique.ptr.runtime.ctor] Status: Tentatively Ready Submitter: Ville Voutilainen Opened: 2015-07-19 Last modified: 2015-11-04
Priority: 2
View all issues with Tentatively Ready status.
Discussion:
According to the wording in 20.8.1.3.1 [unique.ptr.runtime.ctor]/1, this won't work:
unique_ptr<int[], DeleterType> x{nullptr, DeleterType{}};
U is not the same type as pointer, so the first bullet will not do.
U is not a pointer type, so the second bullet will not do.
U is the same type as pointer, or
U is nullptr_t, or
pointer is the same type as element_type*, […]
[2015-10, Kona Saturday afternoon]
MC: Is it the right fix?
GR: It'd be awefully surprising if we had an interface that accepts null pointer values but not std::nullptr_t. I think the PR is good.
STL: Are any of the assignments and reset affected? [No, they don't operate on explicit {pointer, deleter} pairs.]
VV: This is already shipping, has been implemented, has been tested and works fine.
Move to Tentatively ready.
Proposed resolution:
This wording is relative to N4527.
Change 20.8.1.3.1 [unique.ptr.runtime.ctor] as indicated:
template <class U> explicit unique_ptr(U p) noexcept; template <class U> unique_ptr(U p, see below d) noexcept; template <class U> unique_ptr(U p, see below d) noexcept;-1- These constructors behave the same as the constructors that take a pointer parameter in the primary template except that they shall not participate in overload resolution unless either
U is the same type as pointer, or
U is nullptr_t, or
pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].
Section: X [memory.resource.global] Status: Tentatively Ready Submitter: Tim Song Opened: 2015-07-28 Last modified: 2015-11-04
Priority: 2
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts.v2
[memory.resource.global]/p7-8 says that the effects of set_default_resource(r) are
If r is non-null, sets the value of the default memory resource pointer to r, otherwise sets the default memory resource pointer to new_delete_resource().
and the operation has the postcondition
get_default_resource() == r.
When r is null, however, the postcondition cannot be met, since the call sets the default memory resource pointer to new_delete_resource(), and so get_default_resource() would return the value of new_delete_resource(), which is obviously not null and so cannot compare equal to r.
Previous resolution from Tim Song [SUPERSEDED]:This wording is relative to N4480.
Edit [memory.resource.global]/p8 as follows:
-6- memory_resource* set_default_resource(memory_resource* r) noexcept;-7- Effects: If r is non-null, sets the value of the default memory resource pointer to r, otherwise sets the default memory resource pointer to new_delete_resource().
-8- Postconditions: get_default_resource() == r if r is non-null; otherwise, get_default_resource() == new_delete_resource(). […]
[2015-09-15 Geoffrey Romer comments and suggests alternative wording]
Let's just strike X [memory.resource.global]/p8. The problem is that p8 is restating p7 incorrectly, but the solution is not to restate p7 correctly, it's to stop trying to restate p7 at all.
[2015-10, Kona Saturday afternoon]
Move to Tentatively ready
[2015-10-26]
Daniel adjusts wording to lib. fund. v2.
Proposed resolution:
This wording is relative to N4529.
Edit [memory.resource.global]/p8 as follows:
-6- memory_resource* set_default_resource(memory_resource* r) noexcept;-7- Effects: If r is non-null, sets the value of the default memory resource pointer to r, otherwise sets the default memory resource pointer to new_delete_resource().
-8- Postconditions: get_default_resource() == r.[…]
Section: 20.10.7.6 [meta.trans.other] Status: Tentatively Ready Submitter: Mike Spertus Opened: 2015-09-25 Last modified: 2015-11-04
Priority: Not Prioritized
View other active issues in [meta.trans.other].
View all other issues in [meta.trans.other].
View all issues with Tentatively Ready status.
Discussion:
Addresses: fund.ts.v2
In Library Fundamentals 2 (N4529) 3.3.2p3 [meta.trans.other], the definition of invocation traits for a class object f considers when f is called via a function call operator that is matched by the arguments but ignores the possibility that f may be called via a surrogate call function (C++14 13.3.1.1.2 [over.call.object] p2), in which case, the definition of the invocation parameters may be either incorrect or even unsatisfiable.
[2015-10, Kona Saturday afternoon]
AM: Do we have this trait yet? JW: No, it cannot be implemented without compiler support.
Move to tentatively ready
Proposed resolution:
This wording is relative to N4529.
In Library Fundamentals 2, change [meta.trans.other] as indicated:
-3- Within this section, define the invocation parameters of INVOKE(f, t1, t2, ..., tN) as follows, in which T1 is the possibly cv-qualified type of t1 and U1 denotes T1& if t1 is an lvalue or T1&& if t1 is an rvalue:
[…]
If f is a class object, the invocation parameters are the parameters matching t1, ..., tN of the best viable function (C++14 §13.3.3) for the arguments t1, ..., tN among the function call operators and surrogate call functions of f.
[…]