basic_string(const T&, const Alloc&)
turns moves into copiesSection: 27.4.3.3 [string.cons], 27.4.3.7.3 [string.assign] Status: New Submitter: Jonathan Wakely Opened: 2022-01-21 Last modified: 2022-01-30
Priority: 3
View all other issues in [string.cons].
View all issues with New status.
Discussion:
This will do a copy not a move:
struct Str : std::string { Str() = default; Str(Str&& s) : std::string(std::move(s)) { } }; Str s; Str s2(std::move(s));
The problem is that the new C++17 constructor:
basic_string(const T&, const Alloc& = Alloc());
is an exact match, but the basic_string
move constructor requires a derived-to-base conversion.
assign(const T&)
and operator=(const T&)
.
We can fix this by constraining those functions with !derived_from<T, basic_string>
, so
that the move constructor is the only viable function. Libstdc++ has done something very similar since
2017, but using !is_convertible<const T*, const basic_string*>
instead of derived_from
.
[2022-01-30; Reflector poll]
Set priority to 3 after reflector poll.
Jonathan to revise P/R to use is_base_of
or
is_convertible
instead of derived_from
.
Proposed resolution:
This wording is relative to N4901.
Modify 27.4.3.3 [string.cons] as indicated:
template<class T> constexpr explicit basic_string(const T& t, const Allocator& a = Allocator());-7- Constraints:
(7.1) —
is_convertible_v<const T&, basic_string_view<charT, traits>>
istrue
and(7.?) —
derived_from<T, basic_string>
isfalse
and(7.2) —
is_convertible_v<const T&, const charT*>
isfalse
.-8- Effects: Creates a variable,
sv
, as if bybasic_string_view<charT, traits> sv = t;
and then behaves the same asbasic_string(sv.data(), sv.size(), a)
.[…]
template<class T> constexpr basic_string& operator=(const T& t);-27- Constraints:
(27.1) —
is_convertible_v<const T&, basic_string_view<charT, traits>>
istrue
and(27.?) —
derived_from<T, basic_string>
isfalse
and(27.2) —
is_convertible_v<const T&, const charT*>
isfalse
.-28- Effects: Equivalent to:
basic_string_view<charT, traits> sv = t; return assign(sv);
Modify 27.4.3.7.3 [string.assign] as indicated:
template<class T> constexpr basic_string& assign(const T& t);-4- Constraints:
(4.1) —
is_convertible_v<const T&, basic_string_view<charT, traits>>
istrue
and(4.?) —
derived_from<T, basic_string>
isfalse
and(4.2) —
is_convertible_v<const T&, const charT*>
isfalse
.-5- Effects: Equivalent to:
basic_string_view<charT, traits> sv = t; return assign(sv.data(), sv.size());