std::basic_string<CharT,Traits,Allocator>::resize_and_overwrite
| template< class Operation > constexpr void resize_and_overwrite( size_type count, Operation op ); |
(seit C++23) | |
Ändert die Größe des Strings auf maximal count Zeichen und verwendet die vom Benutzer bereitgestellte Operation op, um den möglicherweise unbestimmten Inhalt zu modifizieren und die Länge festzulegen. Dies vermeidet die Kosten für die Initialisierung eines ausreichend großen std::string, wenn dieser als Zeichenarray gedacht ist, das z. B. durch einen C-API-Aufruf gefüllt werden soll.
Diese Funktion führt die folgenden Schritte aus:
- Beschafft zusammenhängenden Speicher, der count + 1 Zeichen enthält, und macht seine ersten k Zeichen gleich den ersten k Zeichen von *this, wobei k das kleinere von count und dem Ergebnis von size() vor dem Aufruf von
resize_and_overwriteist. Sei p der Zeiger auf das erste Zeichen im Speicher.- Die Gleichheit wird so bestimmt, als ob this->compare(0, k, p, k) == 0 geprüft würde.
- Die Zeichen im Bereich
[p + k,p + count]können unbestimmte Werte haben.
- Wertet std::move(op)(p, count) aus, sei r der Rückgabewert.
- Ersetzt den Inhalt von *this durch
[p,p + r)(was die Länge von *this auf r setzt). Macht alle Zeiger und Referenzen auf den Bereich[p,p + count]ungültig.
Wenn r keinen integer-ähnlichen Typ hat, ist das Programm schlecht geformt.
Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert
- std::move(op)(p, count) wirft eine Ausnahme.
- std::move(op)(p, count) modifiziert p oder count.
- r liegt nicht im Bereich
[0,count]. - Jedes Zeichen im Bereich
[p,p + r)hat einen unbestimmten Wert.
Implementierungen wird empfohlen, unnötige Kopien und Allokationen zu vermeiden, indem z. B. p nach dem Aufruf gleich dem Zeiger auf den Anfang des Speichers für Zeichen macht, die für *this zugewiesen wurden. Dies kann identisch mit dem vorhandenen Speicher von *this sein, wenn count kleiner oder gleich capacity() ist.
Inhalt |
[edit] Parameter
| zählt | - | die maximal mögliche neue Größe des Strings |
| op | - | das Funktionsobjekt, das zum Setzen des neuen Inhalts des Strings verwendet wird |
[edit] Ausnahmen
std::length_error, wenn count > max_size(). Alle Ausnahmen, die von der entsprechenden Allocator geworfen werden.
Wenn eine Ausnahme von std::move(op)(p, count) geworfen wird, ist das Verhalten undefiniert. Andernfalls, wenn eine Ausnahme geworfen wird, hat diese Funktion keine Auswirkung.
[edit] Hinweise
resize_and_overwrite macht alle Iteratoren, Zeiger und Referenzen auf *this ungültig, unabhängig davon, ob eine Neuzuweisung stattfindet. Implementierungen dürfen annehmen, dass der Inhalt des Strings nach dem Aufruf von resize_and_overwrite nicht aliased ist.
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_string_resize_and_overwrite |
202110L |
(C++23) | std::basic_string::resize_and_overwrite
|
[edit] Beispiel
Link zum Testen des Beispiels: Compiler Explorer.
#include <algorithm> #include <cassert> #include <cstddef> #include <cstring> #include <iomanip> #include <iostream> #include <string> #include <string_view> static_assert(__cpp_lib_string_resize_and_overwrite); constexpr std::string_view fruits[]{"apple", "banana", "coconut", "date", "elderberry"}; int main() { // A simple case, append only fruits[0]. The string size will be increased. std::string s{"Food: "}; s.resize_and_overwrite(16, [sz = s.size()](char* buf, std::size_t buf_size) noexcept { const auto to_copy = std::min(buf_size - sz, fruits[0].size()); std::memcpy(buf + sz, fruits[0].data(), to_copy); return sz + to_copy; }); std::cout << "1. " << std::quoted(s) << '\n'; // The size shrinking case. Note, that the user's lambda is always invoked. s.resize_and_overwrite(10, [](char* buf, int n) noexcept { return std::find(buf, buf + n, ':') - buf; }); std::cout << "2. " << std::quoted(s) << '\n'; std::cout << "3. Copy data until the buffer is full. Print data and sizes.\n"; std::string food{"Food:"}; const auto resize_to{27}; std::cout << "Initially, food.size: " << food.size() << ", food.capacity: " << food.capacity() << ", resize_to: " << resize_to << ", food: " << std::quoted(food) << '\n'; food.resize_and_overwrite ( resize_to, [food_size = food.size()](char* p, std::size_t n) noexcept -> std::size_t { // p[0]..p[n] is the assignable range // p[0]..p[min(n, food_size) - 1] is the readable range // (contents initially equal to the original string) // Debug print: std::cout << "In Operation(); n: " << n << '\n'; // Copy fruits to the buffer p while there is enough space. char* first = p + food_size; for (char* const end = p + n; const std::string_view fruit : fruits) { char* last = first + fruit.size() + 1; if (last > end) break; *first++ = ' '; std::ranges::copy(fruit, first); first = last; } const auto final_size{static_cast<std::size_t>(first - p)}; // Debug print: std::cout << "In Operation(); final_size: " << final_size << '\n'; assert(final_size <= n); return final_size; // Return value is the actual new length // of the string, must be in range 0..n } ); std::cout << "Finally, food.size: " << food.size() << ", food.capacity: " << food.capacity() << ", food: " << std::quoted(food) << '\n'; }
Mögliche Ausgabe
1. "Food: apple" 2. "Food" 3. Copy data until the buffer is full. Print data and sizes. Initially, food.size: 5, food.capacity: 15, resize_to: 27, food: "Food:" In Operation(); n: 27 In Operation(); final_size: 26 Finally, food.size: 26, food.capacity: 30, food: "Food: apple banana coconut"
[edit] Siehe auch
| ändert die Anzahl der gespeicherten Zeichen (public member function) |