Difference between revisions of "cpp/string/basic string/operator+"
(+) |
(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+( | + | operator+( const basic_string<CharT,Traits,Alloc>& lhs, |
− | + | 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+( | + | operator+( const basic_string<CharT,Traits,Alloc>& lhs, |
− | + | 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>& | + | operator+( const CharT* lhs, |
− | + | 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>& | + | operator+( CharT lhs, |
− | + | 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, | ||
− | + | 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+( | + | operator+( basic_string<CharT,Traits,Alloc>&& lhs, |
− | basic_string<CharT,Traits,Alloc> | + | 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, | ||
− | + | 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+( | + | operator+( basic_string<CharT,Traits,Alloc>&& lhs, |
− | + | 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>&& | + | operator+(const CharT* lhs, |
− | + | 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>&& | + | operator+( CharT lhs, |
− | + | 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 | + | {{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. | ||
− | + | 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: | |
− | + | {{source|1= | |
+ | 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 {{tt|operator+}} invocations, the allocator used for the ultimate result may be controlled by prepending an rvalue {{tt|basic_string}} with the desired allocator: | |
− | + | {{source|1= | |
+ | // 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 {{rlpf|append}}, {{rlpf|insert}}, and {{rlpf|operator+{{=}}}} should be used on a result string constructed with the desired allocator. | |
− | + | }} | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | For better and portable control over allocators, member functions like {{ | + | |
===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}} | ||
− | + | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + |
Revision as of 14:20, 16 November 2018
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(1) | |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(2) | |
template<class CharT, class Traits, class Alloc> basic_string<CharT,Traits,Alloc> |
(3) | |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(4) | |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(5) | |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(6) | (since C++11) |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(7) | (since C++11) |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(8) | (since C++11) |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(9) | (since C++11) |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(10) | (since C++11) |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(11) | (since C++11) |
template< class CharT, class Traits, class Alloc > basic_string<CharT,Traits,Alloc> |
(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 For (6-12), all rvalue |
(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
Because the allocator used by the result of 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 // 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 |
(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) | |
appends characters to the end (public member function) | |
inserts characters (public member function) |