C++26-Bibliothek: Verbesserte Verarbeitung von Strings
C++26 bietet viele kleine Ergänzungen rund um Strings und string_view.
(Bild: Shutterstock.com/calimedia)
- Rainer Grimm
Der kommende Standard C++26 bringt neben den großen Verbesserungen Reflection und Contracts viele kleinere, aber nützliche Ergänzungen. Heute geht es um Strings und um string_view.
Zuallererst: Was ist ein string_view?
std::string_view
Ein std::string_view ist ein nicht besitzender Verweis auf eine Zeichenkette. Sie stellt eine Ansicht einer Zeichenfolge dar. Diese Zeichenfolge kann eine C++-Zeichenkette oder eine C-Zeichenkette sein. Typischerweise bietet C++17 vier Typsynonyme fĂĽr die zugrunde liegenden Zeichentypen.
std::string_view std::basic_string_view<char>
std::wstring_view std::basic_string_view<wchar_t>
std::u16string_view std::basic_string_view<char16_t>
std::u32string_view std::basic_string_view<char32_t>
Eine Frage bleibt: Warum brauchen wir eine std::string_view? Warum hatten Google, LLVM und Bloomberg bereits eine Implementierung einer String-Ansicht? Die Antwort ist einfach: Es ist ressourcenschonend, eine std::string_view zu kopieren. Eine std::string_view benötigt nur zwei Informationen: den Zeiger auf die Zeichenfolge und deren Länge. Wie Sie vielleicht vermuten, bestehen die std::string_view und ihre drei Geschwister hauptsächlich aus Leseoperationen, die der Schnittstelle von std::string folgen. Vor allem, weil sie die neuen Methoden remove_prefix und remove_suffix erhalten.
Testen auf Erfolg oder Misserfolg von <charconv>-Funktionen
Die Funktionen std::to_chars und std::from_chars ließen sich nur umständlich testen: if(res.ec == std::errc{}).
Hier ist ein vereinfachtes Programm von cppreference.com:
// charconv.cpp
#include <charconv>
#include <iomanip>
#include <iostream>
#include <string_view>
#include <system_error>
template <typename T>
void show_to_chars(T value) {
const size_t buf_size = 5;
char buf[buf_size];
std::to_chars_result result = std::to_chars(buf, buf + buf_size, value);
if (result.ec != std::errc{})
std::cout << std::make_error_code(result.ec).message() << '\n';
else{
std::string_view str(buf, result.ptr - buf);
std::cout << std::quoted(str) << '\n';
}
}
int main() {
show_to_chars(42);
show_to_chars(1234567);
}
Das Programm enthält die Header <charconv> für die Zeichenkonvertierung, <iomanip> für Ein-/Ausgabemanipulatoren, <string_view> für die Behandlung von string_views und <system_error> für die Fehlerbehandlung.
Das Funktions-Template show_to_chars nimmt einen Wert beliebigen Typs T entgegen und versucht, ihn in eine Zeichenfolge zu konvertieren. Innerhalb der Funktion wird ein Puffer der Größe 5 deklariert, um die resultierende Zeichenfolge zu speichern. Die Funktion std::to_chars wird dann aufgerufen, um die Umwandlung durchzuführen und das Ergebnis in einem std::to_chars_result-Objekt namens result zu speichern.
Das Ergebnisobjekt enthält einen Zeiger auf das Ende der konvertierten Zeichenfolge und einen Fehlercode. Wenn der Fehlercode ungleich std::errc{} ist, was auf einen Fehler bei der Konvertierung hinweist, wird eine Fehlermeldung mit std::make_error_code(result.ec).message() auf der Konsole ausgegeben. Andernfalls wird ein std::string_view-Objekt erstellt, um die konvertierte Zeichenfolge darzustellen, und die Folge wird mit std::quoted auf der Konsole ausgegeben, um sicherzustellen, dass sie innerhalb von Anführungszeichen angezeigt wird.
In der main-Funktion wird die Funktion show_to_chars zweimal aufgerufen: zuerst mit dem Wert 42 und dann mit dem Wert 1234567. Der erste Aufruf wandelt den Wert 42 erfolgreich in eine Zeichenfolge um und gibt sie aus. Beim zweiten Aufruf wird jedoch versucht, den Wert 1234567 zu konvertieren, der die Puffergröße von 5 überschreitet, was dazu führt, dass eine Fehlermeldung auf der Konsole ausgegeben wird.
Zum Schluss kommt die Ausgabe des Programms:
Dank C++26 gibt die Funktion std::to_chars einen Boolean zurĂĽck und die Funktion show_to_chars kann vereinfacht werden:
template <typename T>
void show_to_chars(T value) {
std::array<char, 5> str;
if (auto result = std::to_chars(str.data(), str.data() + str.size(), value)) {
std::string_view strView(str.data(), result.ptr);
std::cout << std::quoted(strView) << '\n';
}
else
std::cout << std::make_error_code(result.ec).message() << '\n';
}
Innerhalb der Funktion wird ein std::array von Zeichen mit einer festen Größe von 5 deklariert, um die resultierende Zeichenfolge aufzunehmen. Die Funktion std::to_chars wird dann aufgerufen, um die Konvertierung durchzuführen. Diese Funktion versucht, den numerischen Wert in eine Zeichenfolge umzuwandeln und diese im Array str zu speichern. Die Funktion std::to_chars gibt ein std::to_chars_result-Objekt zurück, das einen Zeiger auf das Ende der konvertierten Zeichenfolge und einen Fehlercode enthält.
Die Funktion verwendet eine if-Anweisung, um das Ergebnis des std::to_chars-Aufrufs zu überprüfen. Wenn die Konvertierung erfolgreich ist, wird das Ergebnisobjekt implizit in true konvertiert, und die Funktion fährt mit dem Ausdruck der konvertierten Zeichenfolge fort. Dazu wird ein std::string_view-Objekt strView erzeugt, das die Zeichenfolge vom Anfang des str-Arrays bis zum result.ptr-Zeiger darstellt. Der std::cout-Stream wird dann verwendet, um diese String-Ansicht auf der Konsole auszugeben, wobei std::quoted dafür sorgt, dass die Ausgabe innerhalb von Anführungszeichen angezeigt wird.
Schlägt die Konvertierung fehl, wird das Ergebnisobjekt implizit in false konvertiert und die Funktion gibt stattdessen eine Fehlermeldung aus. Die Fehlermeldung erhält man durch den Aufruf von std::make_error_code(result.ec).message(), der den Fehlercode in eine für Menschen lesbare Zeichenkette umwandelt.
In C++26 gibt es weitere Funktionen zur Verarbeitung von strings und string_views:
- VerknĂĽpfung von Stringstreams mit
std::string_view - Verkettung von Strings und String_Views
- Arithmetische Ăśberladungen von
std::to_stringund Verwendung vonstd::format
Ich habe sie bereits in meinem vorherigen Beitrag vorgestellt: "Ein Ăśberblick ĂĽber C++26: Die Bibliothek".
Wie geht es weiter?
Mein nächster Beitrag zeigt, dass die C++26 Bibliothek noch deutlich mehr zu bieten hat. (rme)