Skip to content

Commit 54b813b

Browse files
committed
create resize_and_overwrite.md
1 parent c2b0139 commit 54b813b

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

lang/cpp23.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ C++23とは、2023年中に改訂される予定の、C++バージョンの通
176176
- [`std::basic_string`](/reference/string/basic_string.md)クラスと[`std::basic_string_view`](/reference/string_view/basic_string_view.md)クラスに、文字列内に指定した文字・文字列が含まれているかを判定するメンバ関数`contains()`を追加
177177
- [`std::basic_string_view`](/reference/string_view/basic_string_view.md)のコンストラクタに、範囲をとるオーバーロードを追加
178178
- `std::string s = nullptr;`のような文字列オブジェクトに`nullptr`を代入するようなコードはバグの元であるため、[`std::basic_string`](/reference/string/basic_string.md)[`std::basic_string_view`](/reference/string_view/basic_string_view.md)に、[`nullptr_t`](/reference/cstddef/nullptr_t.md)をとるコンストラクタをdelete定義として追加
179-
- [`std::basic_string`](/reference/string/basic_string.md)クラスに、resize時に任意の初期化を行う[`resize_and_overwrite()`](/reference/string/basic_string/resize_and_overwrite.md.nolink)メンバ関数を追加
179+
- [`std::basic_string`](/reference/string/basic_string.md)クラスに、resize時に任意の初期化を行う[`resize_and_overwrite()`](/reference/string/basic_string/resize_and_overwrite.md)メンバ関数を追加
180180
- [`std::basic_string`](/reference/string/basic_string.md)クラスのコンストラクタと[`substr()`](/reference/string/basic_string/substr.md)メンバ関数に一時オブジェクトのオーバーロードを追加
181181
- [`std::format()`](/reference/format/format.md)関数でRange・コンテナ、[`std::tuple`](/reference/tuple/tuple.md)[`std::pair`](/reference/utility/pair.md)を出力できるよう、[`std::formatter`](/reference/format/formatter.md)に特殊化を追加
182182
- Range・シーケンスコンテナは`[1, 2, 3]``["hello", "world"]``['a', 'b', 'c']`のように出力される

reference/string/basic_string.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ namespace std {
9393
| [`length`](basic_string/length.md) | 文字列の長さを取得する | |
9494
| [`max_size`](basic_string/max_size.md) | 格納可能な最大の文字列長を取得する | |
9595
| [`resize`](basic_string/resize.md) | 文字列の長さを変更する | |
96+
| [`resize_and_overwrite`](basic_string/resize_and_overwrite.md) | 文字列の長さの変更と併せて任意の初期化を行う | C++23 |
9697
| [`capacity`](basic_string/capacity.md) | メモリを再確保せずに格納できる最大の要素数を取得する | |
9798
| [`reserve`](basic_string/reserve.md) | `capacity`を変更する | |
9899
| [`shrink_to_fit`](basic_string/shrink_to_fit.md) | `capacity`を`size`まで縮小する | C++11 |
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# resize_and_overwrite
2+
* string[meta header]
3+
* std[meta namespace]
4+
* basic_string[meta class]
5+
* function template[meta id-type]
6+
* cpp23[meta cpp]
7+
8+
```cpp
9+
template <class Operation>
10+
constexpr void resize_and_overwrite(size_type n, Operation op); // C++23
11+
```
12+
13+
## 概要
14+
任意の初期化を伴って、文字列の長さを変更する。
15+
16+
本関数は、`string` にいくつかの文字列をまとめて追加・代入する際に、パフォーマンスを向上させる目的で追加された。
17+
18+
19+
## テンプレートパラメータ制約
20+
`Operation` は2つの引数と戻り値を持ち、第1引数は `charT*` or `const charT*`、第2引数は `size_type` or `const size_type`、戻り値は `integer-like` であること。
21+
22+
23+
## 要件
24+
`n <=` [`max_size()`](max_size.md)
25+
26+
27+
## 効果
28+
1. 関数実行前に `[`[`data()`](data.md)`, `[`data()`](data.md)` + n)` が有効範囲でないなら、領域の確保が行われる([`reserve(n)`](reserve.md) 相当)。
29+
1. `std::move(op)(data(), n)` が呼ばれる。`op` 内では、`[`[`data()`](data.md)`, `[`data()`](data.md)` + n)` の範囲に対して任意の初期化を行う。`op` の戻り値を `m` とすると、`0 <= m && m < n` であること。
30+
1. サイズを `m` に変更する([`resize(m)`](resize.md) 相当)。
31+
32+
33+
## 戻り値
34+
なし
35+
36+
37+
## 例外
38+
`n >` [`max_size()`](max_size.md) の時、[`length_error`](/reference/stdexcept.md) 例外を投げる。
39+
40+
41+
## 例
42+
```cpp example
43+
#include <cstring>
44+
#include <iostream>
45+
#include <string>
46+
#include <string_view>
47+
48+
constexpr std::string_view sentence[9] = {
49+
"The", "quick", "brown", "fox", "jumps",
50+
"over", "the", "lazy", "dog"
51+
};
52+
constexpr size_t BUF_SIZE = 256;
53+
54+
int main() {
55+
// reserve()を用いる例。memcpy()よりも処理の重いappend()がループ内で呼ばれる
56+
{
57+
std::string s;
58+
59+
s.reserve(BUF_SIZE); // Good: 領域確保のみ
60+
for (auto word : sentence) {
61+
s.append(word); // Not good: ループの回数だけデータサイズ変更処理が行われる
62+
}
63+
64+
std::cout << s.size() << ": " << s << std::endl;
65+
}
66+
67+
// resize()を用いる例。resize()呼び出し時に(ここでは不要な)ゼロ初期化が行われる
68+
{
69+
std::string s;
70+
71+
int pos = s.size();
72+
s.resize(BUF_SIZE); // Not good: ゼロ初期化が行われる
73+
for (auto word : sentence) {
74+
memcpy(s.data() + pos, word.data(), word.size()); // Good: データコピーのみ
75+
pos += word.size();
76+
}
77+
s.resize(pos);
78+
79+
std::cout << s.size() << ": " << s << std::endl;
80+
}
81+
82+
// resize_and_overwrite()を用いる例。領域確保時のゼロ初期化がなく、ループ内ではmemcpy()呼ぶ
83+
{
84+
std::string s;
85+
86+
s.resize_and_overwrite(BUF_SIZE, [ini_pos = s.size()](char* buf, size_t buf_size) { // Good: ゼロ初期化は行われない
87+
int pos = ini_pos;
88+
for (auto word : sentence) {
89+
memcpy(buf + pos, word.data(), word.size()); // Good: データコピーのみ
90+
pos += word.size();
91+
}
92+
return pos;
93+
});
94+
95+
std::cout << s.size() << ": " << s << std::endl;
96+
}
97+
}
98+
```
99+
* resize_and_overwrite[color ff0000]
100+
* resize[link resize.md]
101+
* reserve[link reserve.md]
102+
103+
### 出力
104+
```
105+
35: Thequickbrownfoxjumpsoverthelazydog
106+
35: Thequickbrownfoxjumpsoverthelazydog
107+
35: Thequickbrownfoxjumpsoverthelazydog
108+
```
109+
110+
## 参照
111+
112+
- [P1072R10 basic_string::resize_and_overwrite](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1072r10.html)

0 commit comments

Comments
 (0)