Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/string/basic string/operator+"

From cppreference.com
< cpp‎ | string‎ | basic string
(+)
(P1165R1, applying as DR against 11)
Line 11: Line 11:
 
template< class CharT, class Traits, class Alloc >
 
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( const CharT* lhs,
+
         operator+( const basic_string<CharT,Traits,Alloc>& lhs,
                  const basic_string<CharT,Traits,Alloc>& rhs );
+
                  const CharT* rhs );
 
}}
 
}}
 
{{dcl | num=3 | 1=
 
{{dcl | num=3 | 1=
template< class CharT, class Traits, class Alloc >
+
template<class CharT, class Traits, class Alloc>
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( CharT lhs,
+
         operator+( const basic_string<CharT,Traits,Alloc>& lhs,
                  const basic_string<CharT,Traits,Alloc>& rhs );
+
                  CharT rhs );
 
}}
 
}}
 
{{dcl | num=4 | 1=
 
{{dcl | num=4 | 1=
 
template< class CharT, class Traits, class Alloc >
 
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( const basic_string<CharT,Traits,Alloc>& lhs,
+
         operator+( const CharT* lhs,
                  const CharT* rhs );
+
                  const basic_string<CharT,Traits,Alloc>& rhs );
 
}}
 
}}
 
{{dcl | num=5 | 1=
 
{{dcl | num=5 | 1=
template<class CharT, class Traits, class Alloc>
+
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( const basic_string<CharT,Traits,Alloc>& lhs,
+
         operator+( CharT lhs,
                  CharT rhs );
+
                  const basic_string<CharT,Traits,Alloc>& rhs );
 
}}
 
}}
 
{{dcl | num=6 | since=c++11 | 1=
 
{{dcl | num=6 | since=c++11 | 1=
Line 36: Line 36:
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
 
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
 
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
                   const basic_string<CharT,Traits,Alloc>& rhs );
+
                   basic_string<CharT,Traits,Alloc>&& rhs );
 
}}
 
}}
 
{{dcl | num=7 | since=c++11 | 1=
 
{{dcl | num=7 | since=c++11 | 1=
 
template< class CharT, class Traits, class Alloc >
 
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( const basic_string<CharT,Traits,Alloc>& lhs,
+
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
                   basic_string<CharT,Traits,Alloc>&& rhs );
+
                   const basic_string<CharT,Traits,Alloc>& rhs );
 
}}
 
}}
 
{{dcl | num=8 | since=c++11 | 1=
 
{{dcl | num=8 | since=c++11 | 1=
Line 48: Line 48:
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
 
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
 
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
                   basic_string<CharT,Traits,Alloc>&& rhs );
+
                   const CharT* rhs );
 
}}
 
}}
 
{{dcl | num=9 | since=c++11 | 1=
 
{{dcl | num=9 | since=c++11 | 1=
 
template< class CharT, class Traits, class Alloc >
 
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+(const CharT* lhs,
+
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
                  basic_string<CharT,Traits,Alloc>&& rhs );
+
                  CharT rhs );
 
}}
 
}}
 
{{dcl | num=10 | since=c++11 | 1=
 
{{dcl | num=10 | since=c++11 | 1=
 
template< class CharT, class Traits, class Alloc >
 
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( CharT lhs,
+
         operator+( const basic_string<CharT,Traits,Alloc>& lhs,
 
                   basic_string<CharT,Traits,Alloc>&& rhs );
 
                   basic_string<CharT,Traits,Alloc>&& rhs );
 
}}
 
}}
Line 65: Line 65:
 
template< class CharT, class Traits, class Alloc >
 
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
+
         operator+(const CharT* lhs,
                  const CharT* rhs );
+
                  basic_string<CharT,Traits,Alloc>&& rhs );
 
}}
 
}}
 
{{dcl | num=12 | since=c++11 | 1=
 
{{dcl | num=12 | since=c++11 | 1=
 
template< class CharT, class Traits, class Alloc >
 
template< class CharT, class Traits, class Alloc >
 
     basic_string<CharT,Traits,Alloc>
 
     basic_string<CharT,Traits,Alloc>
         operator+( basic_string<CharT,Traits,Alloc>&& lhs,
+
         operator+( CharT lhs,
                  CharT rhs );
+
                  basic_string<CharT,Traits,Alloc>&& rhs );
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Returns a string containing characters from {{tt|lhs}} followed by the characters from {{tt|rhs}}.
+
Returns a string containing characters from {{tt|lhs}} followed by the characters from {{tt|rhs}}.  
  
 +
{{rrev|since=c++11|
 +
The allocator used for the result is:
 +
@1-3@ {{c|std::allocator_traits<Alloc>::select_on_container_copy_construction(lhs.get_allocator())
 +
}}
 +
@4-5@ {{c|std::allocator_traits<Alloc>::select_on_container_copy_construction(rhs.get_allocator())
 +
}}
 +
@6-9@ {{c|lhs.get_allocator()}}
 +
@10-12@ {{c|rhs.get_allocator()}}
 +
 +
In other words, if one operand is a {{tt|basic_string}} rvalue, its allocator is used; otherwise, {{tt|select_on_container_copy_construction}} is used on the allocator of the lvalue {{tt|basic_string}} operand. In each case, the left operand is preferred when both are {{tt|basic_string}}s of the same value category.
 +
 +
For {{v|6-12}}, all rvalue {{tt|basic_string}} operands are left in valid but unspecified states.
 +
}}
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
Line 85: Line 98:
  
 
===Return value===
 
===Return value===
 +
A string containing characters from {{tt|lhs}} followed by the characters from {{tt|rhs}}{{rev inl|since=c++11|, using the allocator determined as above}}.
  
1) {{c|basic_string<CharT,Traits,Alloc>(lhs).append(rhs)}}
+
{{rrev|since=c++11|1=
 +
=== Notes ===
 +
{{tt|operator+}} should be used with great caution when stateful allocators are involved{{rev inl|since=c++17| (such as when {{lc|std::pmr::string}} is used)}}. Prior to {{wg21|P1165R1}}, the allocator used for the result was determined by historical accident and can vary from overload to overload for no apparent reason. Moreover, for {{v|1-5}}, the allocator propagation behavior varies across major standard library implementations and differs from the behavior depicted in the standard.
  
2) {{c|basic_string<CharT,Traits,Alloc>(lhs) + rhs}}
+
Because the allocator used by the result of {{tt|operator+}} is sensitive to value category, {{tt|operator+}} is not associative with respect to allocator propagation:
  
3) {{c|basic_string<CharT,Traits,Alloc>(1,lhs) + rhs}}
+
{{source|1=
 +
using my_string = std::basic_string<char, std::char_traits<char>, my_allocator<char>>;
 +
my_string cat();
 +
const my_string& dog();
  
4) {{c|lhs + basic_string<CharT,Traits,Alloc>(rhs)}}
+
my_string meow = /* ... */, woof = /* ... */;
 +
meow + cat() + /*...*/; // uses SOCCC on meow's allocator
 +
woof + dog() + /*...*/; // uses allocator of dog()'s return value instead
  
5) {{c|lhs + basic_string<CharT,Traits,Alloc>(1,rhs)}}
+
meow + woof + meow; // uses SOCCC on meow's allocator
 +
meow + (woof + meow); // uses SOCCC on woof's allocator instead
 +
}}
  
6) {{c|std::move(lhs.append(rhs))}}
+
For a chain of {{tt|operator+}} invocations, the allocator used for the ultimate result may be controlled by prepending an rvalue {{tt|basic_string}} with the desired allocator:
  
7) {{c|std::move(rhs.insert(0, lhs))}}
+
{{source|1=
 +
// use my_favorite_allocator for the final result
 +
my_string(my_favorite_allocator) + meow + woof + cat() + dog();
 +
}}
  
8) {{c|std::move(lhs.append(rhs))}} or {{c|std::move(rhs.insert(0, lhs))}}
+
For better and portable control over allocators, member functions like {{rlpf|append}}, {{rlpf|insert}}, and {{rlpf|operator+{{=}}}} should be used on a result string constructed with the desired allocator.
 
+
}}
9) {{c|std::move(rhs.insert(0, lhs))}}
+
 
+
10) {{c|std::move(rhs.insert(0, 1, lhs))}}
+
 
+
11) {{c|std::move(lhs.append(rhs))}}
+
 
+
12) {{c|std::move(lhs.append(1, rhs))}}
+
 
+
=== Notes ===
+
{{tt|operator+}} should be used with great caution when stateful allocators are involved (such as when {{lc|std::pmr::string}} is used). The allocator used for the result can vary from overload to overload, and the standard is occasionally contradictory. For many of the overloads, the allocator propagation behavior varies across major standard library implementations and differs from the behavior depicted in the standard.
+
 
+
For better and portable control over allocators, member functions like {{ltf|cpp/string/basic_string/append}}, {{ltf|cpp/string/basic_string/insert}}, and {{ltf|cpp/string/basic_string/operator+{{=}}}} should be used on a result string constructed with the desired allocator.
+
  
 
===Example===
 
===Example===
Line 131: Line 145:
 
Hello world!
 
Hello world!
 
}}
 
}}
 +
 +
===Defect reports===
 +
{{dr list begin}}
 +
{{dr list item|paper=P1165R1|std=C++11|before=allocator propagation is haphazard and inconsistent|after=made more consistent}}
 +
{{dr list end}}
  
 
===See also===
 
===See also===
Line 139: Line 158:
 
{{dsc end}}
 
{{dsc end}}
  
[[de:cpp/string/basic string/operator+]]
+
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
[[es:cpp/string/basic string/operator+]]
+
[[fr:cpp/string/basic string/operator+]]
+
[[it:cpp/string/basic string/operator+]]
+
[[ja:cpp/string/basic string/operator+]]
+
[[pt:cpp/string/basic string/operator+]]
+
[[ru:cpp/string/basic string/operator+]]
+
[[zh:cpp/string/basic string/operator+]]
+

Revision as of 14:20, 16 November 2018

 
 
 
std::basic_string
Member functions
Element access
Iterators
Capacity
Modifiers
Search
Operations
Constants
Non-member functions
operator+
I/O
Comparison
(until C++20)(until C++20)(until C++20)(until C++20)(until C++20)(C++20)
Numeric conversions
(C++11)(C++11)(C++11)
(C++11)(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
Literals
Helper classes
Deduction guides (C++17)

 
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( const basic_string<CharT,Traits,Alloc>& lhs,

                   const basic_string<CharT,Traits,Alloc>& rhs );
(1)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( const basic_string<CharT,Traits,Alloc>& lhs,

                   const CharT* rhs );
(2)
template<class CharT, class Traits, class Alloc>

    basic_string<CharT,Traits,Alloc>
        operator+( const basic_string<CharT,Traits,Alloc>& lhs,

                   CharT rhs );
(3)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( const CharT* lhs,

                   const basic_string<CharT,Traits,Alloc>& rhs );
(4)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( CharT lhs,

                   const basic_string<CharT,Traits,Alloc>& rhs );
(5)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( basic_string<CharT,Traits,Alloc>&& lhs,

                   basic_string<CharT,Traits,Alloc>&& rhs );
(6) (since C++11)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( basic_string<CharT,Traits,Alloc>&& lhs,

                   const basic_string<CharT,Traits,Alloc>& rhs );
(7) (since C++11)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( basic_string<CharT,Traits,Alloc>&& lhs,

                   const CharT* rhs );
(8) (since C++11)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( basic_string<CharT,Traits,Alloc>&& lhs,

                   CharT rhs );
(9) (since C++11)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( const basic_string<CharT,Traits,Alloc>& lhs,

                   basic_string<CharT,Traits,Alloc>&& rhs );
(10) (since C++11)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+(const CharT* lhs,

                  basic_string<CharT,Traits,Alloc>&& rhs );
(11) (since C++11)
template< class CharT, class Traits, class Alloc >

    basic_string<CharT,Traits,Alloc>
        operator+( CharT lhs,

                   basic_string<CharT,Traits,Alloc>&& rhs );
(12) (since C++11)

Returns a string containing characters from lhs followed by the characters from rhs.

The allocator used for the result is:

1-3) std::allocator_traits<Alloc>::select_on_container_copy_construction(lhs.get_allocator())
4-5) std::allocator_traits<Alloc>::select_on_container_copy_construction(rhs.get_allocator())
6-9) lhs.get_allocator()
10-12) rhs.get_allocator()

In other words, if one operand is a basic_string rvalue, its allocator is used; otherwise, select_on_container_copy_construction is used on the allocator of the lvalue basic_string operand. In each case, the left operand is preferred when both are basic_strings of the same value category.

For (6-12), all rvalue basic_string operands are left in valid but unspecified states.

(since C++11)

Contents

Parameters

lhs - string, character, or pointer to the first character in a null-terminated array
rhs - string, character, or pointer to the first character in a null-terminated array

Return value

A string containing characters from lhs followed by the characters from rhs, using the allocator determined as above(since C++11).

Notes

operator+ should be used with great caution when stateful allocators are involved (such as when std::pmr::string is used)(since C++17). Prior to P1165R1, the allocator used for the result was determined by historical accident and can vary from overload to overload for no apparent reason. Moreover, for (1-5), the allocator propagation behavior varies across major standard library implementations and differs from the behavior depicted in the standard.

Because the allocator used by the result of operator+ is sensitive to value category, operator+ is not associative with respect to allocator propagation:

using my_string = std::basic_string<char, std::char_traits<char>, my_allocator<char>>;
my_string cat();
const my_string& dog();
 
my_string meow = /* ... */, woof = /* ... */;
meow + cat() + /*...*/; // uses SOCCC on meow's allocator
woof + dog() + /*...*/; // uses allocator of dog()'s return value instead
 
meow + woof + meow; // uses SOCCC on meow's allocator
meow + (woof + meow); // uses SOCCC on woof's allocator instead

For a chain of operator+ invocations, the allocator used for the ultimate result may be controlled by prepending an rvalue basic_string with the desired allocator:

// use my_favorite_allocator for the final result
my_string(my_favorite_allocator) + meow + woof + cat() + dog();

For better and portable control over allocators, member functions like append(), insert(), and operator+=() should be used on a result string constructed with the desired allocator.

(since C++11)

Example

#include <iostream>
#include <string>
 
int main()
{
    std::string s1 = "Hello";
    std::string s2 = "world";
    std::cout << s1 + ' ' + s2 + "!\n";
}

Output:

Hello world!

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
P1165R1 C++11 allocator propagation is haphazard and inconsistent made more consistent

See also

appends characters to the end
(public member function) [edit]
appends characters to the end
(public member function) [edit]
inserts characters
(public member function) [edit]