This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
Section: 23.4.4.1 [string.op.plus] Status: C++11 Submitter: Alisdair Meredith Opened: 2009-06-12 Last modified: 2021-06-06
Priority: Not Prioritized
View all issues with C++11 status.
Discussion:
Many of the basic_string operator+ overloads return an rvalue-reference. Is that really intended?
I'm considering it might be a mild performance tweak to avoid making un-necessary copies of a cheaply movable type, but it opens risk to dangling references in code like:
auto && s = string{"x"} + string{y};
and I'm not sure about:
auto s = string{"x"} + string{y};
[ 2009-10-11 Howard updated Returns: clause for each of these. ]
[ 2009-11-05 Howard adds: ]
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
Proposed resolution:
Strike the && from the return type in the following function signatures:
23.4 [string.classes] p2 Header Synopsis
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, const basic_string<charT,traits,Allocator>& rhs); template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(const basic_string<charT,traits,Allocator>& lhs, basic_string<charT,traits,Allocator>&& rhs); template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, basic_string<charT,traits,Allocator>&& rhs); template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(const charT* lhs, basic_string<charT,traits,Allocator>&& rhs); template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(charT lhs, basic_string<charT,traits,Allocator>&& rhs); template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, const charT* rhs); template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, charT rhs);[string.op+]
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, const basic_string<charT,traits,Allocator>& rhs);Returns: std::move(lhs.append(rhs))
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(const basic_string<charT,traits,Allocator>& lhs, basic_string<charT,traits,Allocator>&& rhs);Returns: std::move(rhs.insert(0, lhs))
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, basic_string<charT,traits,Allocator>&& rhs);Returns: std::move(lhs.append(rhs)) [Note: Or equivalently std::move(rhs.insert(0, lhs)) — end note]
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(const charT* lhs, basic_string<charT,traits,Allocator>&& rhs);Returns: std::move(rhs.insert(0, lhs)).
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(charT lhs, basic_string<charT,traits,Allocator>&& rhs);Returns: std::move(rhs.insert(0, 1, lhs)).
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, const charT* rhs);Returns: std::move(lhs.append(rhs)).
template<class charT, class traits, class Allocator> basic_string<charT,traits,Allocator>&&operator+(basic_string<charT,traits,Allocator>&& lhs, charT rhs);Returns: std::move(lhs.append(1, rhs)).