namespace std {
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs,
const basic_string<charT, traits, Allocator>& rhs); // (1) C++03
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs,
const basic_string<charT, traits, Allocator>& rhs); // (1) C++20
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); // (2) C++11
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(basic_string<charT, traits, Allocator>&& lhs,
const basic_string<charT, traits, Allocator>& rhs); // (2) C++20
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); // (3) C++11
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs,
basic_string<charT, traits, Allocator>&& rhs); // (3) C++20
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); // (4) C++11
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(basic_string<charT, traits, Allocator>&& lhs,
basic_string<charT, traits, Allocator>&& rhs); // (4) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(const charT* lhs,
const basic_string<charT, traits, Allocator>& rhs); // (5) C++03
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(const charT* lhs,
const basic_string<charT, traits, Allocator>& rhs); // (5) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(const charT* lhs,
basic_string<charT, traits, Allocator>&& rhs); // (6) C++11
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(const charT* lhs,
basic_string<charT, traits, Allocator>&& rhs); // (6) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(charT lhs,
const basic_string<charT, traits, Allocator>& rhs); // (7) C++03
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(charT lhs,
const basic_string<charT, traits, Allocator>& rhs); // (7) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(charT lhs,
basic_string<charT, traits, Allocator>&& rhs); // (8) C++11
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(charT lhs,
basic_string<charT, traits, Allocator>&& rhs); // (8) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs,
const charT* rhs); // (9) C++03
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs,
const charT* rhs); // (9) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(basic_string<charT, traits, Allocator>&& lhs,
const charT* rhs); // (10) C++11
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(basic_string<charT, traits, Allocator>&& lhs,
const charT* rhs); // (10) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs,
charT rhs); // (11) C++03
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs,
charT rhs); // (11) C++20
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(basic_string<charT, traits, Allocator>&& lhs,
charT rhs); // (12) C++11
template <class charT, class traits, class Allocator>
constexpr basic_string<charT, traits, Allocator>
operator+(basic_string<charT, traits, Allocator>&& lhs,
charT rhs); // (12) C++20
}
概要
basic_string
オブジェクトの連結を行う。
戻り値
C++17まで
-
(1)
basic_string<charT, traits, Allocator>(lhs).append(rhs)
-
(4)
std::move(lhs.append(rhs))
(std::move(rhs.insert(0, lhs))
とも等価) -
(5)
basic_string<charT, traits, Allocator>(lhs) + rhs
-
(7)
basic_string<charT, traits, Allocator>(1, lhs) + rhs
-
(9)
lhs + basic_string<charT, traits, Allocator>(rhs)
-
(11)
lhs + basic_string<charT, traits, Allocator>(1, rhs)
C++20から
-
(1)(9) : 以下と等価
basic_string<charT, traits, Allocator> r = lhs; r.append(rhs); return r;
-
(2)(10) : 以下と等価
lhs.append(rhs); return std::move(lhs);
-
(3)(6) : 以下と等価
rhs.insert(0, lhs); return std::move(rhs);
-
(4) : 呼び出しの後でも
lhs
とrhs
は有効だが未規定な状態のままであることを除いて、以下と等価
lhs.append(rhs); return std::move(lhs);
-
(5) : 以下と等価
basic_string<charT, traits, Allocator> r = rhs; r.insert(0, lhs); return r;
-
(7) : 以下と等価
-
(8) : 以下と等価
-
(11) : 以下と等価
basic_string<charT, traits, Allocator> r = lhs; r.push_back(rhs); return r;
-
(12) : 以下と等価
lhs.push_back(rhs); return std::move(lhs);
備考
(5)、(6) の形式の lhs
、および、(9)、(10) の形式の rhs
の文字列長算出のために traits::length()
が使用される
アロケータの伝播
C++20からこの演算子による文字列連結時にアロケータがどのように伝播するかが変更された。C++17までの仕様及び各実装とC++20からの各オーバーロード利用時の結果オブジェクトへのアロケータ供給元は次のようになる。なお、SOCCCはselect_on_container_copy_construction
の略。
オーバーロード | C++17まで | GCC | clang | MSVC | C++20から |
---|---|---|---|---|---|
(1) : lhs + rhs |
lhs からのSOCCC |
lhs からのSOCCC |
lhs |
新規にデフォルト構築 | lhs からのSOCCC |
(2) : std::move(lhs) + rhs |
lhs |
lhs |
lhs |
lhs |
lhs |
(3) : lhs + std::move(rhs) |
rhs |
rhs |
rhs |
rhs |
rhs |
(4) : std::move(lhs) + std::move(rhs) |
lhs またはrhs |
lhs |
lhs |
lhs |
lhs |
(5) : "lhs" + rhs |
新規にデフォルト構築 | 新規にデフォルト構築 | rhs |
新規にデフォルト構築 | lhs からのSOCCC |
(6) : "lhs" + std::move(rhs) |
rhs |
rhs |
rhs |
rhs |
rhs |
(7) : 'l' + rhs |
新規にデフォルト構築 | 新規にデフォルト構築 | rhs |
新規にデフォルト構築 | lhs からのSOCCC |
(8) : 'l' + std::move(rhs) |
rhs |
rhs |
rhs |
rhs |
rhs |
(9) : lhs + "rhs" |
新規にデフォルト構築 | lhs からのSOCCC |
lhs |
新規にデフォルト構築 | lhs からのSOCCC |
(10) : std::move(lhs) + "rhs" |
lhs |
lhs |
lhs |
lhs |
lhs |
(11) : lhs + 'r' |
新規にデフォルト構築 | lhs からのSOCCC |
lhs |
新規にデフォルト構築 | lhs からのSOCCC |
(12) : std::move(lhs) + 'r' |
lhs |
lhs |
lhs |
lhs |
lhs |
表にあるように、C++17までの仕様に完全に準拠している実装は無かった上に各実装によって伝播仕様がバラバラだったため、この変更によって影響を受けるコードはほぼ無いと思われる。
例
#include <iostream>
#include <string>
int main()
{
std::string s1("Hell");
std::string s2("world");
std::string s3 = s1 + 'o' + ", " + s2 + '!';
std::cout << s3 << '\n';
}
出力
Hello, world!
関連項目
名前 | 説明 |
---|---|
append |
文字/文字列を追加する |
push_back |
文字を追加する |
insert |
文字/文字列を挿入する |