Namensräume
Varianten
Aktionen

Benutzerdefinierte Literale (seit C++11)

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefiniert (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Ermöglicht es ganzzahligen, Gleitkomma-, Zeichen- und Zeichenkettenliteralen, Objekte eines benutzerdefinierten Typs zu erzeugen, indem ein benutzerdefiniertes Suffix definiert wird.

Inhalt

[bearbeiten] Syntax

Ein benutzerdefiniertes Literal ist ein Ausdruck einer der folgenden Formen

Dezimalliteral ud-suffix (1)
Oktalliteral ud-suffix (2)
Hexadezimalliteral ud-suffix (3)
Binärliteral ud-suffix (4)
fraktionales-literal exponent-teil (optional) ud-suffix (5)
ziffernfolge exponent-teil ud-suffix (6)
Zeichenliteral ud-suffix (7)
Zeichenkettenliteral ud-suffix (8)
1-4) benutzerdefinierte Ganzzahlliterale, wie z. B. 12_km
5-6) benutzerdefinierte Gleitkommaliterale, wie z. B. 0.5_Pa
7) benutzerdefiniertes Zeichenliteral, wie z. B. 'c'_X
8) benutzerdefiniertes Zeichenkettenliteral, wie z. B. "abd"_L oder u"xyz"_M
Dezimalliteral - wie in Ganzzahlliteral, eine nicht-null Dezimalziffer gefolgt von null oder mehr Dezimalziffern
Oktalliteral - wie in Ganzzahlliteral, eine Null gefolgt von null oder mehr Oktalziffern
Hexadezimalliteral - wie in Ganzzahlliteral, 0x oder 0X gefolgt von einer oder mehreren Hexadezimalziffern
Binärliteral - wie in Ganzzahlliteral, 0b oder 0B gefolgt von einer oder mehreren Binärziffern
Ziffernfolge - wie in Gleitkommaliteral, eine Folge von Dezimalziffern
Fraktionales-literal - wie in Gleitkommaliteral, entweder eine ziffernfolge gefolgt von einem Punkt (123.) oder eine optionale ziffernfolge gefolgt von einem Punkt und einer weiteren ziffernfolge (1.0 oder .12)
Exponent-teil - wie in Gleitkommaliteral, der Buchstabe e oder der Buchstabe E gefolgt von einem optionalen Vorzeichen und einer ziffernfolge
Zeichenliteral - wie in Zeichenliteral
string-literal - wie in Zeichenkettenliteral, einschließlich roher Zeichenkettenliterale
ud-suffix - ein Bezeichner, eingeführt durch einen Literaloperator oder eine Literaloperator-Vorlage (siehe unten)

In den Ganzzahl- und Gleitkomma- Ziffernfolgen sind optionale Trennzeichen ' zwischen zwei beliebigen Ziffern erlaubt.

(seit C++14)

Wenn ein Token mit einer benutzerdefinierten Literalsyntax und einer regulären Literalsyntax übereinstimmt, wird es als reguläres Literal angenommen (d. h., es ist unmöglich, LL in 123LL zu überladen).

Wenn der Compiler ein benutzerdefiniertes Literal mit ud-suffix X antrifft, führt er eine qualifizierte Namenssuche durch und sucht nach einer Funktion mit dem Namen operator""X. Wenn die Suche keine Deklaration findet, ist das Programm schlecht geformt. Andernfalls:

1) Für benutzerdefinierte Ganzzahlliterale,
a) wenn die Überladungsmenge einen Literaloperator mit dem Parametertyp unsigned long long enthält, wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator ""X(n ULL), wobei n das Literal ohne ud-suffix ist;
b) andernfalls muss die Überladungsmenge entweder, aber nicht beide, einen rohen Literaloperator oder eine numerische Literaloperator-Vorlage enthalten. Wenn die Überladungsmenge einen rohen Literaloperator enthält, wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator""X("n ");
c) andernfalls, wenn die Überladungsmenge eine numerische Literaloperator-Vorlage enthält, wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator""X<'c1 ', 'c2 ', 'c3 '..., 'ck '>(), wobei c1 bis ck die einzelnen Zeichen von n sind und alle aus dem Basiszeichensatz stammen.
2) Für benutzerdefinierte Gleitkommaliterale,
a) Wenn die Überladungsmenge einen Literaloperator mit dem Parametertyp long double enthält, wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator ""X(f  L), wobei f das Literal ohne ud-suffix ist;
b) andernfalls muss die Überladungsmenge entweder, aber nicht beide, einen rohen Literaloperator oder eine numerische Literaloperator-Vorlage enthalten. Wenn die Überladungsmenge einen rohen Literaloperator enthält, wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator ""X("f  ");
c) andernfalls, wenn die Überladungsmenge eine numerische Literaloperator-Vorlage enthält, wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator""X<'c1 ', 'c2 ', 'c3 '..., 'ck '>(), wobei c1 bis ck die einzelnen Zeichen von f sind und alle aus dem Basiszeichensatz stammen.
3) Für benutzerdefinierte Zeichenkettenliterale sei str das Literal ohne ud-suffix
a) Wenn die Überladungsmenge eine Zeichenkettenliteral-Operator-Vorlage mit einem Nicht-Typ-Template-Parameter enthält, für den str ein wohlgeformtes Template-Argument ist, dann wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator ""X<str>();
(seit C++20)
b) andernfalls wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator ""X (str, len), wobei len die Länge des Zeichenkettenliterals ist, ohne das abschließende Nullzeichen.
4) Für benutzerdefinierte Zeichenliterale wird der benutzerdefinierte Literalausdruck als Funktionsaufruf behandelt: operator ""X(ch), wobei ch das Literal ohne ud-suffix ist.
long double operator ""_w(long double);
std::string operator ""_w(const char16_t*, size_t);
unsigned    operator ""_w(const char*);
 
int main()
{
    1.2_w;    // calls operator ""_w(1.2L)
    u"one"_w; // calls operator ""_w(u"one", 3)
    12_w;     // calls operator ""_w("12")
    "two"_w;  // error: no applicable literal operator
}

Wenn Zeichenkettenliterale in Übersetzungsphase 6 verkettet werden, werden auch benutzerdefinierte Zeichenkettenliterale verkettet, und ihre ud-suffixe werden für die Verkettung ignoriert, mit der Ausnahme, dass nur ein Suffix bei allen verketteten Literalen erscheinen darf.

int main()
{
    L"A" "B" "C"_x;  // OK: same as L"ABC"_x
    "P"_x "Q" "R"_y; // error: two different ud-suffixes (_x and _y)
}

[bearbeiten] Literaloperatoren

Die Funktion, die von einem benutzerdefinierten Literal aufgerufen wird, ist als Literaloperator (oder, wenn es eine Vorlage ist, Literaloperator-Vorlage) bekannt. Sie wird wie jede andere Funktion oder Funktionsvorlage im Namespace-Gültigkeitsbereich deklariert (sie kann auch eine Freundschaftsfunktion, eine explizite Instanziierung oder Spezialisierung einer Funktionsvorlage sein oder durch eine using-Deklaration eingeführt werden), mit den folgenden Einschränkungen:

Der Name dieser Funktion kann eine der beiden Formen haben:

operator "" bezeichner (1) (veraltet)
operator benutzerdefiniertes-zeichenkettenliteral (2)
identifier - der bezeichner, der als ud-suffix für die benutzerdefinierten Literale verwendet wird, die diese Funktion aufrufen werden
benutzerdefiniertes-zeichenkettenliteral - die Zeichenfolge "" gefolgt, ohne Leerzeichen, von der Zeichenfolge, die zum ud-suffix wird
1) Deklariert einen Literaloperator.
2) Deklariert einen Literaloperator. Diese Syntax ermöglicht die Verwendung von Sprachschlüsselwörtern und reservierten Bezeichnern als ud-suffixe, z. B. operator ""if aus dem Header <complex>.

ud-suffix muss mit dem Unterstrich _ beginnen: Suffixe, die nicht mit einem Unterstrich beginnen, sind für die von der Standardbibliothek bereitgestellten Literaloperatoren reserviert. Er darf auch keine doppelten Unterstriche __ enthalten: solche Suffixe sind ebenfalls reserviert.

Wenn der Literaloperator eine Vorlage ist, muss er eine leere Parameterliste haben und darf nur einen Template-Parameter haben, der eine Nicht-Typ-Template-Parameterliste mit dem Elementtyp char sein muss (in diesem Fall als numerischer Literaloperator-Vorlage bezeichnet)

template<char...>
double operator ""_x();

oder ein Nicht-Typ-Template-Parameter vom Klassentyp (in diesem Fall als Zeichenkettenliteraloperator-Vorlage bezeichnet)

struct A { constexpr A(const char*); };
 
template<A a>
A operator ""_a();
(seit C++20)

Nur die folgenden Parameterlisten sind für Literaloperatoren zulässig:

( const char* ) (1)
( unsigned long long int ) (2)
( long double ) (3)
( char ) (4)
( wchar_t ) (5)
( char8_t ) (6) (seit C++20)
( char16_t ) (7)
( char32_t ) (8)
( const char*, std::size_t ) (9)
( const wchar_t*, std::size_t ) (10)
( const char8_t*, std::size_t ) (11) (seit C++20)
( const char16_t*, std::size_t ) (12)
( const char32_t*, std::size_t ) (13)
1) Literaloperatoren mit dieser Parameterliste sind die rohen Literaloperatoren, die als Fallback für ganzzahlige und Gleitkomma-Benutzerdefinierte Literale verwendet werden (siehe oben).
2) Literaloperatoren mit diesen Parameterlisten sind die Literaloperatoren der ersten Wahl für benutzerdefinierte Ganzzahlliterale.
3) Literaloperatoren mit diesen Parameterlisten sind die Literaloperatoren der ersten Wahl für benutzerdefinierte Gleitkommaliterale.
4-8) Literaloperatoren mit diesen Parameterlisten werden von benutzerdefinierten Zeichenliteralen aufgerufen.
9-13) Literaloperatoren mit diesen Parameterlisten werden von benutzerdefinierten Zeichenkettenliteralen aufgerufen.

Standardargumente sind nicht erlaubt.

C-Sprachbindung ist nicht erlaubt.

Abgesehen von den oben genannten Einschränkungen sind Literaloperatoren und Literaloperator-Vorlagen normale Funktionen (und Funktionsvorlagen), sie können inline oder constexpr deklariert werden, sie können interne oder externe Bindung haben, sie können explizit aufgerufen werden, ihre Adressen können genommen werden usw.

#include <string>
 
void        operator ""_km(long double); // OK, will be called for 1.0_km
void        operator "" _km(long double); // same as above, deprecated
std::string operator ""_i18n(const char*, std::size_t); // OK
 
template<char...>
double operator ""_pi(); // OK
float  operator ""_e(const char*); // OK
 
// error: suffix must begin with underscore
float operator ""Z(const char*);
 
// error: all names that begin with underscore followed by uppercase
// letter are reserved (NOTE: a space between "" and _).
double operator"" _Z(long double);
 
// OK. NOTE: no space between "" and _.
double operator""_Z(long double);
 
// OK: literal operators can be overloaded
double operator ""_Z(const char* args);
 
int main() {}

[bearbeiten] Anmerkungen

Seit der Einführung von benutzerdefinierten Literalen ist der Code, der Format-Makrokonstanten für ganzzahlige Typen fester Breite ohne Leerzeichen nach dem vorhergehenden Zeichenkettenliteral verwendet, ungültig geworden: std::printf("%"PRId64"\n",INT64_MIN); muss ersetzt werden durch std::printf("%" PRId64"\n",INT64_MIN);.

Aufgrund des maximalen Munch müssen benutzerdefinierte Ganzzahl- und Gleitkommaliterale, die auf p, P,(seit C++17) e und E enden und von den Operatoren + oder - gefolgt werden, durch ein Leerzeichen oder Klammern im Quellcode von dem Operator getrennt werden.

long double operator""_E(long double);
long double operator""_a(long double);
int operator""_p(unsigned long long);
 
auto x = 1.0_E+2.0;   // error
auto y = 1.0_a+2.0;   // OK
auto z = 1.0_E +2.0;  // OK
auto q = (1.0_E)+2.0; // OK
auto w = 1_p+2;       // error
auto u = 1_p +2;      // OK

Dasselbe gilt für den Punktoperator, der auf ein ganzzahliges oder Gleitkomma-Benutzerdefiniertes Literal folgt.

#include <chrono>
 
using namespace std::literals;
 
auto a = 4s.count();   // Error
auto b = 4s .count();  // OK
auto c = (4s).count(); // OK

Andernfalls wird ein einzelnes ungültiges Präprozessor-Zahlentoken (z. B. 1.0_E+2.0 oder 4s.count) gebildet, was zu einem Kompilierungsfehler führt.

Feature-Testmakro Wert Std Feature
__cpp_user_defined_literals 200809L (C++11) Benutzerdefinierte Literale

[bearbeiten] Schlüsselwörter

operator

[bearbeiten] Beispiele

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <numbers>
#include <string>
 
// used as conversion from degrees (input param) to radians (returned output)
constexpr long double operator""_deg_to_rad(long double deg)
{
    long double radians = deg * std::numbers::pi_v<long double> / 180;
    return radians;
}
 
// used with custom type
struct mytype
{
    unsigned long long m;
};
 
constexpr mytype operator""_mytype(unsigned long long n)
{
    return mytype{n};
}
 
// used for side-effects
void operator""_print(const char* str)
{
    std::cout << str << '\n';
}
 
#if __cpp_nontype_template_args < 201911
 
std::string operator""_x2 (const char* str, std::size_t)
{
    return std::string{str} + str;
}
 
#else // C++20 string literal operator template
 
template<std::size_t N>
struct DoubleString
{
    char p[N + N - 1]{};
 
    constexpr DoubleString(char const(&pp)[N])
    {
        std::ranges::copy(pp, p);
        std::ranges::copy(pp, p + N - 1);
    }
};
 
template<DoubleString A>
constexpr auto operator""_x2()
{
    return A.p;
}
 
#endif // C++20
 
int main()
{
    double x_rad = 90.0_deg_to_rad;
    std::cout << std::fixed << x_rad << '\n';
 
    mytype y = 123_mytype;
    std::cout << y.m << '\n';
 
    0x123ABC_print;
    std::cout << "abc"_x2 << '\n';
}

Ausgabe

1.570796
123
0x123ABC
abcabc

[bearbeiten] Standardbibliothek

Die folgenden Literaloperatoren sind in der Standardbibliothek definiert:

Definiert im Inline-Namespace std::literals::complex_literals
ein std::complex Literal, das eine rein imaginäre Zahl darstellt.
(function) [edit]
Definiert im Inline-Namespace std::literals::chrono_literals
ein std::chrono::duration Literal, das Stunden repräsentiert
(Funktion) [bearbeiten]
ein std::chrono::duration Literal, das Minuten repräsentiert
(Funktion) [bearbeiten]
ein std::chrono::duration Literal, das Sekunden repräsentiert
(Funktion) [bearbeiten]
ein std::chrono::duration Literal, das Millisekunden repräsentiert
(Funktion) [bearbeiten]
ein std::chrono::duration Literal, das Mikrosekunden repräsentiert
(Funktion) [bearbeiten]
ein std::chrono::duration Literal, das Nanosekunden repräsentiert
(Funktion) [bearbeiten]
ein std::chrono::year Literal, das ein bestimmtes Jahr repräsentiert
(Funktion) [bearbeiten]
ein std::chrono::day Literal, das einen Tag eines Monats repräsentiert
(Funktion) [bearbeiten]
Definiert im Inline-Namespace std::literals::string_literals
konvertiert ein Zeichenkettenliteral in basic_string
(function) [edit]
Definiert im Inline-Namespace std::literals::string_view_literals
erzeugt eine Zeichenansicht eines Zeichenkettenliteral
(Funktion) [edit]

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 1473 C++11 Leerzeichen zwischen "" und ud-suffix war
erforderlich in der Deklaration von Literaloperatoren.
optional gemacht.
CWG 1479 C++11 Literaloperatoren konnten Standardargumente haben. verboten
CWG 2521 C++11 operator"" _Bq war schlecht geformt (keine Diagnose
erforderlich), da er den reservierten Bezeichner _Bq verwendet.
veraltete die Literaloperator-Syntax
mit Leerzeichen zwischen "" und ud-suffix.