zurück zum Artikel

Softwareentwicklung: Platzhalter und erweiterter Zeichensatz in C++26

Rainer Grimm
HolzwĂŒrfel mit dem Schriftzug C++

(Bild: SerbioVas/Shutterstock)

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.

FĂŒr C++26 sind neben den großen ErgĂ€nzungen Reflection und Contracts, die ich in den vergangenen Wochen vorgestellt habe [1], 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 [2] 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.

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 [3])


URL dieses Artikels:
https://www.heise.de/-9991701

Links in diesem Artikel:
[1] https://www.heise.de/developer/ModernesCplusplus-3691794.html
[2] https://en.cppreference.com/w/cpp/language/charset#Basic_character_set
[3] mailto:rme@ix.de