This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
Section: 23.4.3.3 [string.cons], 23.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.
This is a regression since C++14, because the move constructor was called in C++14. This problem also exists for 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 23.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>> is true and
(7.?) — derived_from<T, basic_string> is false and
(7.2) — is_convertible_v<const T&, const charT*> is false.
-8- Effects: Creates a variable, sv, as if by basic_string_view<charT, traits> sv = t; and then behaves the same as basic_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>> is true and
(27.?) — derived_from<T, basic_string> is false and
(27.2) — is_convertible_v<const T&, const charT*> is false.
-28- Effects: Equivalent to:
basic_string_view<charT, traits> sv = t; return assign(sv);
Modify 23.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>> is true and
(4.?) — derived_from<T, basic_string> is false and
(4.2) — is_convertible_v<const T&, const charT*> is false.
-5- Effects: Equivalent to:
basic_string_view<charT, traits> sv = t; return assign(sv.data(), sv.size());