basic_string
misuses "Effects: Equivalent to"Section: 27.4.3.7.3 [string.assign] Status: Resolved Submitter: Jonathan Wakely Opened: 2017-02-03 Last modified: 2020-09-06
Priority: 3
View all other issues in [string.assign].
View all issues with Resolved status.
Discussion:
basic_string::assign(size_type n, charT c);
says:
Effects: Equivalent to
assign(basic_string(n, c))
.
This requires that a new basic_string
is constructed, using a
default-constructed allocator, potentially allocating memory, and then
that new string is copy-assigned to *this
, potentially propagating the
allocator. This must be done even if this->capacity() > n
,
because memory allocation and allocator propagation are observable side
effects. If the allocator doesn't propagate and isn't equal to
this->get_allocator()
then a second allocation may be required. This
can't be right; it won't even compile if the allocator isn't default
constructible.
basic_string::assign(InputIterator first, InputIterator last)
has a
similar problem, even if the iterators are random access and
this->capacity() > distance(first, last)
.
basic_string::assign(std::initializer_list<charT>
doesn't say
"Equivalent to" so maybe it's OK to not allocate anything if the list
fits in the existing capacity.
basic_string::append(size_type, charT)
and
basic_string::append(InputIterator, InputIterator)
have the same
problem, although they don't propagate the allocator, but still
require at least one, maybe two allocations.
A partial fix would be to ensure all the temporaries are constructed
with get_allocator()
so that they don't require default constructible
allocators, and so propagation won't alter allocators. The problem of
observable side effects is still present (the temporary might need to
allocate memory, even if this->capacity()
is large) but arguably it's
unspecified when construction allocates, to allow for small-string
optimisations.
[2017-03-04, Kona]
Set priority to 3. Thomas to argue on reflector that this is NAD.
[2017-03-07, LWG reflector discussion]
Thomas and Jonathan remark that LWG 2788 fixed most cases except the allocator respectance and provide wording for this:
Resolved by the adoption of P1148 in San Diego.
Proposed resolution:
This wording is relative to N4659.
Change 27.4.3.7.3 [string.assign] as indicated:
basic_string& assign(size_type n, charT c);-22- Effects: Equivalent to
assign(basic_string(n, c, get_allocator()))
.