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.

In Pocket speichern vorlesen Druckansicht 6 Kommentare lesen
HolzwĂĽrfel mit dem Schriftzug C++

(Bild: SerbioVas/Shutterstock)

Lesezeit: 3 Min.
Von
  • Rainer Grimm
Inhaltsverzeichnis

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.

Modernes C++ – Rainer Grimm

Rainer Grimm ist seit vielen Jahren als Softwarearchitekt, Team- und Schulungsleiter tätig. Er schreibt gerne Artikel zu den Programmiersprachen C++, Python und Haskell, spricht aber auch gerne und häufig auf Fachkonferenzen. Auf seinem Blog Modernes C++ beschäftigt er sich intensiv mit seiner Leidenschaft C++.

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.

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.

  • raw1 ist definiert als R„@(Hello\n)@“, das den Text Hello\n enthält, ohne dass \n als Zeilenumbruch interpretiert wird
  • raw2 ist definiert als R„$(Hello\t)$“, das den Text Hello\t enthält, ohne \t als Tabulatorzeichen zu interpretieren
  • raw3 ist definiert als R„`(Hello\b)`“, das den Text Hello\b enthält, ohne dass \b als Backspace interpretiert wird.

Zum Schluss sehen wir die Ausgabe des Programms:

Die Kernsprache von C++26 bietet weitere Verbesserungen, wie die Pack-Indexierung, an. Darüber werde ich im nächsten Blogartikel schreiben. (rme)