Created on 2022-01-21.00:00:00 last changed 34 months ago
Proposed resolution:
This wording is relative to N4901.
Modify [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 [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());
[ 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
.
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.History | |||
---|---|---|---|
Date | User | Action | Args |
2022-01-30 17:05:36 | admin | set | messages: + msg12331 |
2022-01-22 16:22:48 | admin | set | messages: + msg12278 |
2022-01-21 00:00:00 | admin | create |