Softwareentwicklung: Platzhalter und erweiterter Zeichensatz in C++26
Platzhalter sind eine gute Möglichkeit, um Variablen zu markieren, die nicht mehr benötigt werden. Außerdem wird der Zeichensatz von C++26 erweitert.
(Bild: SerbioVas/Shutterstock)
- Rainer Grimm
Für C++26 sind neben den großen Ergänzungen Reflection und Contracts, die ich in den vergangenen Wochen vorgestellt habe, auch ein paar kleinere, nützliche Ergänzungen vorgesehen.
Platzhalter
Strukturierte Bindungen sind ein Feature von C++17, mit dem man mehrere Variablen an die Elemente eines strukturierten Objekts binden kann.
Das folgende Programm demonstriert die Verwendung von Tupeln und strukturierten Bindungen, um mehrere Werte aus einer Funktion zurĂĽckzugeben und wieder auszupacken.
// placeholder1.cpp
#include <tuple>
#include <string>
#include <iostream>
// Function that returns three values
std::tuple<int, std::string, double> getThreeValues() {
int intValue = 42;
std::string strValue = "example";
double doubleValue = 3.14;
return std::make_tuple(intValue, strValue, doubleValue);
}
int main() {
// Retrieve the three values using structured binding
auto [intValue, strValue, doubleValue] = getThreeValues();
// Print the values
std::cout << "Integer: " << intValue << '\n';
std::cout << "String: " << strValue << '\n';
std::cout << "Double: " << doubleValue << '\n';
}
Die Funktion getThreeValues ist so definiert, dass sie ein Tupel zurückgibt, das drei verschiedene Datentypen enthält: einen int, einen std::string und einen double. Diese Werte werden dann mit std::make_tuple in ein Tupel gepackt und von der Funktion zurückgegeben.
In der main-Funktion ruft das Programm die drei von getThreeValues zurückgegebenen Werte mithilfe strukturierter Bindungen ab. Strukturierte Bindungen ermöglichen es dem Programm, das Tupel direkt in drei separate Variablen zu packen: intValue, strValue und doubleValue. Das macht den Code lesbarer und einfacher als das manuelle Auspacken des Tupels.
Manchmal braucht man nicht alle drei Werte aus der Funktion getThreeValues.
// placeholder2.cpp
#include <tuple>
#include <string>
#include <iostream>
// Function that returns three values
std::tuple<int, std::string, double> getThreeValues() {
int intValue = 42;
std::string strValue = "example";
double doubleValue = 3.14;
return std::make_tuple(intValue, strValue, doubleValue);
}
int main() {
// Retrieve the three values using structured binding
auto [_, strValue, doubleValue] = getThreeValues();
// Print the values
std::cout << "String: " << strValue << '\n';
std::cout << "Double: " << doubleValue << '\n';
}
Dieses Mal wird der intValue aus der Funktion getThreeValues im nachfolgenden Code nicht benötigt. Aus Konvention binde ich ihn an den Unterstrich.
Das bedeutet gleichzeitig, dass der Compiler keine Warnung ausgibt, weil die Variable _ nicht verwendet wird:
Leider kann das intuitive _ nur einmal als Bezeichner verwendet werden. Diese Einschränkung entfällt mit C++26:
// placeholder3.cpp
#include <tuple>
#include <string>
#include <iostream>
// Function that returns three values
std::tuple<int, std::string, double> getThreeValues() {
int intValue = 42;
std::string strValue = "example";
double doubleValue = 3.14;
return std::make_tuple(intValue, strValue, doubleValue);
}
int main() {
// Retrieve the three values using structured binding
auto [_, strValue, _] = getThreeValues();
// Print the values
std::cout << "String: " << strValue << '\n';
}
In dieser Variante wird weder der intValue noch der doubleValue aus der Funktion getThreeValues benötigt. Ich verwende konsequent zwei Unterstriche.
Erweiterter Zeichensatz
Drei neue Zeichen sind im Basiszeichensatz verfĂĽgbar:
Das folgende Programm verwendet alle drei fĂĽr Raw-String-Literale.
#include <iostream>
int main() {
std::cout << '\n';
auto raw1 = R"@(Hello\n)@";
auto raw2 = R"$(Hello\t)$";
auto raw3 = R"`(Hello\b)`";
std::cout << "raw1: " << raw1 << '\n';
std::cout << "raw2: " << raw2 << '\n';
std::cout << "raw3: " << raw3 << '\n';
std::cout << '\n';
}
Das Programm definiert dann drei Raw-String-Literale: raw1, raw2 und raw3. Raw-String-Literale werden in C++ in delimiter(...)delimiter eingeschlossen, wobei delimiter eine beliebige Folge von Zeichen sein kann. So kann die Zeichenkette Sonderzeichen wie \n, \t oder \b enthalten, ohne dass sie interpretiert werden mĂĽssen.
raw1ist definiert alsR„@(Hello\n)@“, das den TextHello\nenthält, ohne dass\nals Zeilenumbruch interpretiert wirdraw2ist definiert alsR„$(Hello\t)$“, das den TextHello\tenthält, ohne\tals Tabulatorzeichen zu interpretierenraw3ist definiert alsR„`(Hello\b)`“, das den TextHello\benthält, ohne dass\bals Backspace interpretiert wird.
Zum Schluss sehen wir die Ausgabe des Programms:
Wie geht's weiter?
Die Kernsprache von C++26 bietet weitere Verbesserungen, wie die Pack-Indexierung, an. Darüber werde ich im nächsten Blogartikel schreiben. (rme)