User-defined literals (since C++11)
Ermöglicht es Ganzzahl-, Gleitkomma-, Zeichen- und Zeichenkettenliteralen, Objekte benutzerdefinierten Typs zu erzeugen, indem ein benutzerdefinierter Suffix definiert wird.
Inhaltsverzeichnis |
Syntax
Ein benutzerdefinierter 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) | ||||||||
| Bruchkonstante Exponententeil (optional) ud-suffix | (5) | ||||||||
| Ziffernfolge Exponententeil ud-suffix | (6) | ||||||||
| Zeichenliteral ud-suffix | (7) | ||||||||
| Zeichenkettenliteral ud-suffix | (8) | ||||||||
| decimal-literal | - | identisch wie in Ganzzahlliteral , eine Dezimalziffer ungleich null gefolgt von null oder mehr Dezimalziffern |
| octal-literal | - | identisch wie in Ganzzahlliteral , eine Null gefolgt von null oder mehr Oktalziffern |
| hex-literal | - |
identisch wie in
Ganzzahlliteral
,
0x
oder
0X
gefolgt von einer oder mehr Hexadezimalziffern
|
| binary-literal | - |
identisch wie in
Ganzzahlliteral
,
0b
oder
0B
gefolgt von einer oder mehr Binärziffern
|
| digit-sequence | - | identisch wie in Gleitkommaliteral , eine Folge von Dezimalziffern |
| fractional-constant | - | identisch wie in Gleitkommaliteral , entweder eine digit-sequence gefolgt von einem Punkt ( 123 . ) oder eine optionale digit-sequence gefolgt von einem Punkt und einer weiteren digit-sequence ( 1.0 oder .12 ) |
| exponent-part | - |
identisch wie in
Gleitkommaliteral
, der Buchstabe
e
oder der Buchstabe
E
gefolgt von optionalem Vorzeichen, gefolgt von
digit-sequence
|
| character-literal | - | identisch wie in Zeichenliteral |
| string-literal | - | identisch wie in Zeichenkettenliteral , einschließlich Raw-Zeichenkettenliteralen |
| ud-suffix | - | ein Bezeichner, eingeführt durch eine Literaloperator - oder Literaloperator-Template -Deklaration (siehe unten ) |
|
In den
Integer-
und
Fließkomma-
Ziffernfolgen sind optionale Trennzeichen
|
(since C++14) |
Wenn ein Token sowohl auf eine benutzerdefinierte Literalsyntax als auch auf eine reguläre Literalsyntax passt, wird angenommen, dass es sich um ein reguläres Literal handelt (das heißt, es ist unmöglich,
LL
in
123LL
zu überladen).
Wenn der Compiler auf ein benutzerdefiniertes Literal mit dem
ud-suffix
X
stößt, führt er einen
unqualified name lookup
durch, um nach einer Funktion mit dem Namen
operator
""
X
zu suchen. Wenn die Suche keine Deklaration findet, ist das Programm fehlerhaft. Andernfalls,
|
a)
Wenn der Überladungssatz einen String-Literal-Operator-Template mit einem konstanten Template-Parameter enthält, für den
str
ein gültiges Template-Argument ist, dann wird der benutzerdefinierte Literalausdruck als Funktionsaufruf
operator
""
X
<
str
>
(
)
behandelt;
|
(seit C++20) |
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; // ruft operator ""_w(1.2L) auf u"one"_w; // ruft operator ""_w(u"one", 3) auf 12_w; // ruft operator ""_w("12") auf "two"_w; // Fehler: kein passender Literal-Operator }
Wenn die Verkettung von Zeichenkettenliteralen in Übersetzungsphase 6 stattfindet, werden auch benutzerdefinierte Zeichenkettenliterale verkettet, und ihre ud-suffix e werden für die Verkettung ignoriert, mit der Ausnahme, dass nur ein Suffix auf allen verketteten Literalen erscheinen darf:
int main() { L"A" "B" "C"_x; // OK: gleiche Bedeutung wie L"ABC"_x "P"_x "Q" "R"_y; // Fehler: zwei verschiedene UD-Suffixe (_x und _y) }
Literaloperatoren
Die von einem benutzerdefinierten Literal aufgerufene Funktion wird als literal operator bezeichnet (oder, falls es sich um ein Template handelt, literal operator template ). Sie wird wie jede andere Funktion oder function template im Namensbereich deklariert (sie kann auch eine Friend-Funktion, eine explizite Instanziierung oder Spezialisierung eines Funktions-Templates sein oder durch eine using-Deklaration eingeführt werden), mit Ausnahme der folgenden Einschränkungen:
Der Name dieser Funktion kann eine von zwei Formen haben:
operator ""
Bezeichner
|
(1) | (veraltet) | |||||||
operator
benutzerdefinierter-Zeichenkettenliteral
|
(2) | ||||||||
| identifier | - | der identifier , der als ud-suffix für die benutzerdefinierten Literale verwendet wird, die diese Funktion aufrufen |
| user-defined-string-literal | - |
die Zeichenfolge
""
gefolgt, ohne Leerzeichen, von der Zeichenfolge, die zum
ud-suffix
wird
|
ud-suffix
muss mit dem Unterstrich
_
beginnen: Die Suffixe, die nicht mit dem Unterstrich beginnen, sind für die von der Standardbibliothek bereitgestellten Literaloperatoren reserviert. Es darf ebenfalls keine doppelten Unterstriche
__
enthalten: Solche Suffixe sind ebenfalls reserviert.
Wenn der Literaloperator eine Vorlage ist, muss er eine leere Parameterliste haben und kann nur einen Template-Parameter besitzen, der ein konstantes Template-Parameterpaket mit Elementtyp char sein muss (in diesem Fall wird er als numerischer Literaloperator-Template bezeichnet):
template<char...> double operator ""_x();
|
oder einen konstanten Template-Parameter vom Klassentyp (in diesem Fall wird er als String-Literal-Operator-Template 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) | ||||||||
Standardargumente sind nicht erlaubt.
C language linkage ist nicht erlaubt.
Abgesehen von den oben genannten Einschränkungen sind Literaloperatoren und Literaloperatortemplates normale Funktionen (und Funktionsvorlagen). Sie können als inline oder constexpr deklariert werden, sie können internen oder externen Linkage haben, sie können explizit aufgerufen werden, ihre Adressen können genommen werden, usw.
#include <string> void operator ""_km(long double); // OK, wird für 1.0_km aufgerufen void operator "" _km(long double); // wie oben, veraltet std::string operator ""_i18n(const char*, std::size_t); // OK template<char...> double operator ""_pi(); // OK float operator ""_e(const char*); // OK // Fehler: Suffix muss mit Unterstrich beginnen float operator ""Z(const char*); // Fehler: alle Namen, die mit Unterstrich gefolgt von Großbuchstaben beginnen, // sind reserviert (HINWEIS: ein Leerzeichen zwischen "" und _). double operator"" _Z(long double); // OK. HINWEIS: kein Leerzeichen zwischen "" und _. double operator""_Z(long double); // OK: Literaloperatoren können überladen werden double operator ""_Z(const char* args); int main() {}
Hinweise
Seit der Einführung benutzerdefinierter Literale ist Code, der Format-Makrokonstanten für Ganzzahltypen fester Breite ohne Leerzeichen nach dem vorangehenden Zeichenkettenliteral verwendet, ungültig geworden: std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; muss ersetzt werden durch std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; .
Aufgrund von
maximal munch
müssen benutzerdefinierte Ganzzahl- und Gleitkommaliterale, die auf
p
,
P
,
(since C++17)
e
und
E
enden, wenn sie von den Operatoren
+
oder
-
gefolgt werden, im Quellcode durch Leerzeichen oder Klammern vom 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; // Fehler 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; // Fehler auto u = 1_p +2; // OK
Gleiches gilt für den Punktoperator nach einem ganzzahligen oder Gleitkomma-Benutzerdefinierten Literal:
#include <chrono> using namespace std::literals; auto a = 4s.count(); // Fehler auto b = 4s .count(); // OK auto c = (4s).count(); // OK
Andernfalls wird ein einzelner ungültiger Präprozessor-Zahlentoken (z.B., 1.0 _E + 2.0 oder 4s. count ) gebildet, was dazu führt, dass die Kompilierung fehlschlägt.
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_user_defined_literals
|
200809L
|
(C++11) | Benutzerdefinierte Literale |
Schlüsselwörter
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
Standardbibliothek
Die folgenden Literaloperatoren sind in der Standardbibliothek definiert:
|
Definiert im Inline-Namensraum
std::literals::complex_literals
|
|
|
ein
std::complex
Literal, das eine rein imaginäre Zahl repräsentiert
(Funktion) |
|
|
Definiert im Inline-Namensraum
std::literals::chrono_literals
|
|
|
(C++14)
|
ein
std::chrono::duration
Literal, das Stunden repräsentiert
(Funktion) |
|
(C++14)
|
ein
std::chrono::duration
Literal, das Minuten repräsentiert
(Funktion) |
|
(C++14)
|
ein
std::chrono::duration
Literal, das Sekunden repräsentiert
(Funktion) |
|
(C++14)
|
ein
std::chrono::duration
Literal, das Millisekunden repräsentiert
(Funktion) |
|
(C++14)
|
ein
std::chrono::duration
Literal, das Mikrosekunden repräsentiert
(Funktion) |
|
(C++14)
|
ein
std::chrono::duration
Literal, das Nanosekunden repräsentiert
(Funktion) |
|
(C++20)
|
ein
std::chrono::year
Literal, das ein bestimmtes Jahr repräsentiert
(Funktion) |
|
(C++20)
|
ein
std::chrono::day
Literal, das einen Tag eines Monats repräsentiert
(Funktion) |
|
Definiert im Inline-Namensraum
std::literals::string_literals
|
|
|
(C++14)
|
konvertiert ein Zeichenarray-Literal zu
basic_string
(Funktion) |
|
Definiert im Inline-Namensraum
std::literals::string_view_literals
|
|
|
(C++17)
|
erstellt einen String-View eines Zeichenarray-Literals
(Funktion) |
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 1473 | C++11 |
Leerzeichen zwischen
""
und
ud-suffix
war
bei der Deklaration von Literaloperatoren erforderlich |
optional gemacht |
| CWG 1479 | C++11 | Literaloperatoren konnten Standardargumente haben | verboten |
| CWG 2521 | C++11 |
operator
""
_Bq
war fehlerhaft (keine Diagnose
erforderlich), da es die reservierte Kennung
_Bq
verwendet
|
veraltete die Literaloperator-Syntax
mit Leerzeichen zwischen "" und ud-suffix |