zurück zum Artikel

Softwareentwicklung: Die Formatierungsbibliothek in C++20

Rainer Grimm
Schreibmaschine

(Bild: Dirtymono/Shutterstock)

Die Serie zur Formatierungsbibliothek in C++20, dessen Basis das C++20-Buch des Blogautors ist, sollen als Nachschlagewerk dienen.

Obwohl Peter Gottschling zwei großartige Blogartikel über die Formatierungsbibliothek in C++20 geschrieben hat ("std::format in C++20 [1]", "C++20: std::format um benutzerdefinierte Datentypen erweitern [2]"), werde ich erneut über die Formatierungsbibliothek schreiben. Der Grund dafür ist einfach: Peters Artikel hat eine tolle Einführung und Übersicht gegeben. Ich möchte alle Details vorstellen, damit alle diesen und die kommenden Artikel als Nachschlagewerk nutzen können.

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++.

C++20 unterstützt die folgenden Formatierungsfunktionen:

Die Funktionen std::format und std::format_to sind funktional äquivalent zu ihren Pendants std::vformat und std::vformat_to, aber sie unterscheiden sich in einigen Punkten:

Die Formatierungsfunktionen akzeptieren eine beliebige Anzahl von Argumenten. Das folgende Programm vermittelt einen ersten Eindruck von den Funktionen std::format, std::format_to und std::format_to_n.

// format.cpp

#include <format>
#include <iostream>
#include <iterator>
#include <string>
 
int main() {
    
    std::cout << '\n';

    std::cout << std::format("Hello, C++{}!\n", "20") 
      << '\n';                                         // (1)

    std::string buffer;
 
    std::format_to(                                    // (2)
        std::back_inserter(buffer), 
        "Hello, C++{}!\n",          
        "20");    
        
    std::cout << buffer << '\n';

    buffer.clear(); 

    std::format_to_n(                                  // (3)
        std::back_inserter(buffer), 5, 
        "Hello, C++{}!\n",          
        "20");    
        
    std::cout << buffer << '\n';

    
    std::cout << '\n';
   
}

Das Programm zeigt in (1) direkt die formatierte Zeichenkette an. Die Aufrufe in den (2) und (3) verwenden jedoch einen String als Puffer. Außerdem schiebt std::format_to_n nur fünf Zeichen in den Puffer.

Hier ist also das entsprechende Programm, das std::vformat und std::vformat_n verwendet:

// formatRuntime.cpp

#include <format>
#include <iostream>
#include <iterator>
#include <string>
 
int main() {
    
    std::cout << '\n';

    std::string formatString = "Hello, C++{}!\n";

    std::cout << std::vformat(formatString, 
                              std::make_format_args("20"))
              << '\n';                                     // (1)

    std::string buffer;
 
    std::vformat_to(                                       // (2)
        std::back_inserter(buffer), 
        formatString,          
        std::make_format_args("20"));    
        
    std::cout << buffer << '\n';
   
}

Der formatString in den (1) und (2) ist ein lValue.

Vermutlich ist der spannendste Teil der Formatierungsfunktionen der Formatstring ("Hallo, C++{}!\n").

Die Syntax des Formatstrings ist bei den Formatierungsfunktionen std::format, std::format_to, std::format_to_n, std::vformat und std::vformat_to identisch. Ich verwende std::format in meinen Beispielen.

Der Formatring FormatString besteht aus

Ein Ersatzfeld hat das Format { }.

Mit der Argument-ID lässt sich der Index der Argumente in Args angeben. Die IDs beginnen mit 0. Wenn keine Argument-ID angegeben bst, werden die Felder in der gleichen Reihenfolge ausgefüllt, in der die Argumente angegeben werden. Entweder müssen alle Ersetzungsfelder eine Argument-ID verwenden oder keine; das heißt std::format("{}, {}", "Hallo", "Welt") und std::format("{1}, {0}", "Welt", "Hallo") werden beide kompiliert, aber std::format("{1}, {}", "Welt", "Hallo") nicht.

std::formatter und seine Spezialisierungen definieren die Formatspezifikation für die Argumenttypen.

Die Tatsache, dass die Formatstrings eine Compile-Zeit-Variable sind, hat zwei interessante Konsequenzen: Performanz und Sicherheit.

Im nächsten Blogartikel werde ich die Theorie mit der Praxis ergänzen.

(rme [4])


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

Links in diesem Artikel:
[1] https://www.heise.de/blog/std-format-in-C-20-4919132.html
[2] https://www.heise.de/blog/C-20-std-format-um-benutzterdefinierte-Datentypen-erweitern-4921299.html
[3] https://github.com/fmtlib/fmt
[4] mailto:rme@ix.de