This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.
function::operator=
handles allocators incorrectlySection: 22.10.17.3.2 [func.wrap.func.con] Status: NAD Submitter: Pablo Halpern Opened: 2014-05-23 Last modified: 2015-05-05
Priority: 1
View all other issues in [func.wrap.func.con].
View all issues with NAD status.
Discussion:
The Effects clauses for the assignment operator for class template function
are written as code that constructs a temporary function
and then swaps it with *this
. The intention appears to be that assignment should have the strong exception guarantee, i.e., *this
is not modified if an exception is thrown. However, the current description is incorrect when *this
was constructed using an allocator.
Part of the problem is the under-specification of swap
, which does not state the allocator requirements or allocator postconditions. If swap
behaves like the rest of the standard library, swapping function objects constructed with different allocators would be undefined behavior. Alternatively swap
could exchange the allocators, though I would argue against this specification.
For either specification of swap
, the current Effects clauses for operator=
are incorrect. If swap
does not exchange the allocators, then operator=
would have undefined behavior, which is clearly not desired. If swap
does exchange the allocators, then operator=
would always leave the left-hand side (lhs) of the assignment with a default allocator. The latter would be surprising behavior, as the allocator instance is normally unchanged for the lifetime of an object (for good reason), and is certainly not reset to default arbitrarily.
The desired behavior is that assignment would leave the allocator of the lhs unchanged. The way to achieve this behavior is to construct the temporary function
using the original allocator. Unfortunately, we cannot describe the desired behavior in pure code, because there is no way to name the type-erased value of the allocator. (N3916 would improve this situation for the Library Fundamentals TS, but even with those changes, there is no way to recover the original type of the allocator.) The PR below, therefore, uses pseudo-code, inventing a fictitious ALLOCATOR_OF(f)
expression that evaluates to the actual allocator type, even if that allocator was type erased. I have implemented this PR successfully.
Previous resolution [SUPERSEDED]:
This wording is relative to N3936.
Change 22.10.17.3.2 [func.wrap.func.con] as indicated:
In the following descriptions,
ALLOCATOR_OF(f)
is a copy of the allocator specified in the construction offunction
f
, orallocator<char>()
if no allocator was specified.function& operator=(const function& f);-12- Effects:
function(allocator_arg, ALLOCATOR_OF(*this), f).swap(*this);
-13- Returns:
*this
function& operator=(function&& f);-14- Effects:
Replaces the target of*this
with the target off
.function(allocator_arg, ALLOCATOR_OF(*this), std::move(f)).swap(*this);
-15- Returns:
*this
function& operator=(nullptr_t);-16- Effects: If
*this != nullptr
, destroys the target ofthis
.-17- Postconditions:
!(*this)
. The allocator is unchanged.-18- Returns:
*this
-?- Throws: Nothing.
template<class F> function& operator=(F&& f);-19- Effects:
function(allocator_arg, ALLOCATOR_OF(*this), std::forward<F>(f)).swap(*this);
-20- Returns:
*this
-21- Remarks: This assignment operator shall not participate in overload resolution unless
declval<typename decay<F>::type&>()
isCallable
(20.9.11.2) for argument typesArgTypes...
and return typeR
.template<class F> function& operator=(reference_wrapper<F> f);-22- Effects:
function(allocator_arg, ALLOCATOR_OF(*this), f).swap(*this);
-23- Returns:
*this
[2015-05, Lenexa]
STL: think this is NAD, don't think this is implementable or even should be.
STL: think this issue should be dealt with the same as 2370, don't think this should be done ever.
STL: NAD because there is nothing broken here.
STL: already fixed operator= noexcept
so Throws nothing is not needed
STL: nothing to salvage here
MC: consensus for NAD
Proposed resolution:
There was consensus by the committee that the issue does not constitute as defect.