Namespaces
Variants

User-defined literals (since C++11)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Permet aux littéraux entiers, à virgule flottante, caractères et chaînes de produire des objets de type défini par l'utilisateur en définissant un suffixe défini par l'utilisateur.

Table des matières

Syntaxe

Un littéral défini par l'utilisateur est une expression de l'une des formes suivantes

decimal-literal ud-suffix (1)
octal-literal ud-suffix (2)
hex-literal ud-suffix (3)
binary-literal ud-suffix (4)
fractional-constant exponent-part  (optionnel) ud-suffix (5)
digit-sequence exponent-part ud-suffix (6)
character-literal ud-suffix (7)
string-literal ud-suffix (8)
1-4) littéraux entiers définis par l'utilisateur, tels que 12 _km
5-6) littéraux à virgule flottante définis par l'utilisateur, tels que 0.5 _Pa
7) littéral de caractère défini par l'utilisateur, tel que 'c' _X
8) littéral de chaîne défini par l'utilisateur, tel que "abd" _L ou u "xyz" _M
decimal-literal - identique au littéral entier , un chiffre décimal non nul suivi de zéro ou plusieurs chiffres décimaux
octal-literal - identique au littéral entier , un zéro suivi de zéro ou plusieurs chiffres octaux
hex-literal - identique au littéral entier , 0x ou 0X suivi d'un ou plusieurs chiffres hexadécimaux
binary-literal - identique au littéral entier , 0b ou 0B suivi d'un ou plusieurs chiffres binaires
digit-sequence - identique au littéral flottant , une séquence de chiffres décimaux
fractional-constant - identique au littéral flottant , soit une digit-sequence suivie d'un point ( 123 . ) ou une digit-sequence optionnelle suivie d'un point et d'une autre digit-sequence ( 1.0 ou .12 )
exponent-part - identique au littéral flottant , la lettre e ou la lettre E suivie d'un signe optionnel, suivi d'une digit-sequence
character-literal - identique au littéral de caractère
string-literal - identique au littéral de chaîne , incluant les littéraux de chaîne bruts
ud-suffix - un identificateur, introduit par une déclaration d' opérateur littéral ou de modèle d'opérateur littéral (voir ci-dessous )

Dans les séquences de chiffres des littéraux entiers et flottants , les séparateurs optionnels ' sont autorisés entre deux chiffres quelconques.

(depuis C++14)

Si un jeton correspond à la syntaxe d'un littéral défini par l'utilisateur et à une syntaxe de littéral régulier, il est considéré comme un littéral régulier (c'est-à-dire qu'il est impossible de surcharger LL dans 123LL ).

Lorsque le compilateur rencontre un littéral défini par l'utilisateur avec le ud-suffix X , il effectue une recherche de nom non qualifié , cherchant une fonction avec le nom operator "" X . Si la recherche ne trouve pas de déclaration, le programme est mal formé. Sinon,

1) Pour les littéraux entiers définis par l'utilisateur,
a) si l'ensemble de surcharge inclut un opérateur littéral avec le type de paramètre unsigned long long , l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X ( n  ULL ) , où n est le littéral sans ud-suffix ;
b) sinon, l'ensemble de surcharge doit inclure soit, mais pas les deux, un opérateur littéral brut ou un modèle d'opérateur littéral numérique. Si l'ensemble de surcharge inclut un opérateur littéral brut, l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X ( " n  ") ;
c) sinon, si l'ensemble de surcharge inclut un modèle d'opérateur littéral numérique, l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X < ' c1  ' , ' c2  ' , ' c3  ' ..., ' ck  ' > ( ) , où c1 .. ck sont les caractères individuels de n et tous appartiennent au jeu de caractères de base .
2) Pour les littéraux à virgule flottante définis par l'utilisateur,
a) Si l'ensemble de surcharge inclut un opérateur littéral avec le type de paramètre long double , l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X ( f   L ) , où f est le littéral sans ud-suffix ;
b) sinon, l'ensemble de surcharge doit inclure soit, mais pas les deux, un opérateur littéral brut ou un modèle d'opérateur littéral numérique. Si l'ensemble de surcharge inclut un opérateur littéral brut, l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X ( " f   ") ;
c) sinon, si l'ensemble de surcharge inclut un modèle d'opérateur littéral numérique, l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X < ' c1  ' , ' c2  ' , ' c3  ' ..., ' ck  ' > ( ) , où c1 .. ck sont les caractères individuels de f et tous appartiennent au jeu de caractères de base .
3) Pour les littéraux de chaîne définis par l'utilisateur, soit str le littéral sans ud-suffix :
a) Si l'ensemble de surcharge inclut un modèle d'opérateur de littéral de chaîne avec un paramètre de modèle constant pour lequel str est un argument de modèle valide, alors l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X < str > ( ) ;
(depuis C++20)
b) sinon, l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X ( str, len ) , où len est la longueur du littéral de chaîne, excluant le caractère nul de terminaison.
4) Pour les littéraux de caractères définis par l'utilisateur, l'expression littérale définie par l'utilisateur est traitée comme un appel de fonction operator "" X ( ch ) , où ch est le littéral sans le suffixe-ud .
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;    // appelle operator ""_w(1.2L)
    u"one"_w; // appelle operator ""_w(u"one", 3)
    12_w;     // appelle operator ""_w("12")
    "two"_w;  // erreur : aucun opérateur littéral applicable
}

Lorsque la concaténation de littéraux de chaîne a lieu dans la phase de traduction 6 , les littéraux de chaîne définis par l'utilisateur sont également concaténés, et leurs ud-suffix sont ignorés pour la concaténation, sauf qu'un seul suffixe peut apparaître sur tous les littéraux concaténés :

int main()
{
    L"A" "B" "C"_x;  // OK : identique à L"ABC"_x
    "P"_x "Q" "R"_y; // erreur : deux suffixes utilisateur différents (_x et _y)
}

Opérateurs littéraux

La fonction appelée par un littéral défini par l'utilisateur est appelée opérateur littéral (ou, s'il s'agit d'un template, opérateur littéral template ). Elle est déclarée comme toute autre fonction ou fonction template au niveau de l'espace de noms (elle peut également être une fonction amie, une instanciation explicite ou une spécialisation d'un template de fonction, ou être introduite par une using-declaration), à l'exception des restrictions suivantes :

Le nom de cette fonction peut avoir l'une des deux formes :

operator "" identifiant (1) (obsolète)
operator littéral-chaîne-défini-par-utilisateur (2)
identifier - l' identifiant à utiliser comme suffixe-ud pour les littéraux définis par l'utilisateur qui appelleront cette fonction
user-defined-string-literal - la séquence de caractères "" suivie, sans espace, par la séquence de caractères qui devient le suffixe-ud
1) Déclare un opérateur littéral.
2) Déclare un opérateur littéral. Cette syntaxe permet d'utiliser les mots-clés du langage et les identifiants réservés comme ud-suffix es, par exemple, operator "" if de l'en-tête <complex> .

ud-suffix doit commencer par le soulignement _ : les suffixes qui ne commencent pas par le soulignement sont réservés pour les opérateurs littéraux fournis par la bibliothèque standard. Il ne peut pas contenir de doubles soulignements __ non plus : de tels suffixes sont également réservés.

Si l'opérateur littéral est un modèle, il doit avoir une liste de paramètres vide et ne peut avoir qu'un seul paramètre de modèle, qui doit être un pack de paramètres de modèle constant avec le type d'élément char (auquel cas il est connu comme un opérateur littéral numérique modèle ):

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

ou un paramètre de modèle constant de type classe (auquel cas il est connu sous le nom d' opérateur de modèle de littéral de chaîne ) :

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

Seules les listes de paramètres suivantes sont autorisées pour les opérateurs littéraux :

( const char * ) (1)
( unsigned long long int ) (2)
( long double ) (3)
( char ) (4)
( wchar_t ) (5)
( char8_t ) (6) (depuis 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) (depuis C++20)
( const char16_t * , std::size_t ) (12)
( const char32_t * , std::size_t ) (13)
1) Les opérateurs littéraux avec cette liste de paramètres sont les opérateurs littéraux bruts , utilisés comme solutions de repli pour les littéraux définis par l'utilisateur entiers et à virgule flottante (voir ci-dessus)
2) Les opérateurs littéraux avec ces listes de paramètres sont l'opérateur littéral de premier choix pour les littéraux entiers définis par l'utilisateur
3) Les opérateurs littéraux avec ces listes de paramètres sont les opérateurs littéraux de premier choix pour les littéraux flottants définis par l'utilisateur
4-8) Les opérateurs littéraux avec ces listes de paramètres sont appelés par les littéraux de caractères définis par l'utilisateur
9-13) Les opérateurs littéraux avec ces listes de paramètres sont appelés par les littéraux de chaîne définis par l'utilisateur

Les arguments par défaut ne sont pas autorisés.

La linkage de langage C n'est pas autorisée.

En dehors des restrictions ci-dessus, les opérateurs littéraux et les modèles d'opérateurs littéraux sont des fonctions normales (et des modèles de fonctions), ils peuvent être déclarés inline ou constexpr, ils peuvent avoir une liaison interne ou externe, ils peuvent être appelés explicitement, leurs adresses peuvent être prises, etc.

#include <string>
void        operator ""_km(long double); // OK, sera appelé pour 1.0_km
void        operator "" _km(long double); // identique au précédent, déprécié
std::string operator ""_i18n(const char*, std::size_t); // OK
template<char...>
double operator ""_pi(); // OK
float  operator ""_e(const char*); // OK
// erreur : le suffixe doit commencer par un tiret bas
float operator ""Z(const char*);
// erreur : tous les noms commençant par un tiret bas suivi d'une lettre majuscule
// sont réservés (NOTE : un espace entre "" et _).
double operator"" _Z(long double);
// OK. NOTE : pas d'espace entre "" et _.
double operator""_Z(long double);
// OK : les opérateurs littéraux peuvent être surchargés
double operator ""_Z(const char* args);
int main() {}

Notes

Depuis l'introduction des littéraux définis par l'utilisateur, le code qui utilise les constantes de macro de format pour les types entiers de largeur fixe sans espace après le littéral de chaîne précédent est devenu invalide : std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; doit être remplacé par std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; .

En raison du maximal munch , les littéraux entiers et flottants définis par l'utilisateur se terminant par p , P , (depuis C++17) e et E , lorsqu'ils sont suivis des opérateurs + ou - , doivent être séparés de l'opérateur par un espace ou des parenthèses dans le code source :

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;   // erreur
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;       // erreur
auto u = 1_p +2;      // OK

Il en va de même pour l'opérateur point suivant un littéral défini par l'utilisateur de type entier ou flottant :

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

Sinon, un seul jeton de prétraitement numérique invalide (par exemple, 1.0 _E + 2.0 ou 4s. count ) est formé, ce qui entraîne l'échec de la compilation.

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_user_defined_literals 200809L (C++11) Littéraux définis par l'utilisateur

Mots-clés

operator

Exemples

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <numbers>
#include <string>
// utilisé comme conversion de degrés (paramètre d'entrée) en radians (sortie retournée)
constexpr long double operator""_deg_to_rad(long double deg)
{
    long double radians = deg * std::numbers::pi_v<long double> / 180;
    return radians;
}
// utilisé avec un type personnalisé
struct mytype
{
    unsigned long long m;
};
constexpr mytype operator""_mytype(unsigned long long n)
{
    return mytype{n};
}
// utilisé pour les effets de bord
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';
}

Sortie :

1.570796
123
0x123ABC
abcabc

Bibliothèque standard

Les opérateurs littéraux suivants sont définis dans la bibliothèque standard :

Défini dans l'espace de noms en ligne std::literals::complex_literals
un littéral std::complex représentant un nombre purement imaginaire
(fonction)
Défini dans l'espace de noms en ligne std::literals::chrono_literals
un littéral std::chrono::duration représentant des heures
(fonction)
un littéral std::chrono::duration représentant des minutes
(fonction)
un littéral std::chrono::duration représentant des secondes
(fonction)
un littéral std::chrono::duration représentant des millisecondes
(fonction)
un littéral std::chrono::duration représentant des microsecondes
(fonction)
un littéral std::chrono::duration représentant des nanosecondes
(fonction)
un littéral std::chrono::year représentant une année particulière
(fonction)
un littéral std::chrono::day représentant un jour du mois
(fonction)
Défini dans l'espace de noms en ligne std::literals::string_literals
convertit un littéral de tableau de caractères en basic_string
(fonction)
Défini dans l'espace de noms en ligne std::literals::string_view_literals
crée une vue de chaîne d'un littéral de tableau de caractères
(fonction)

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement correct
CWG 1473 C++11 l'espace blanc entre "" et ud-suffix était
requis dans la déclaration des opérateurs littéraux
rendu optionnel
CWG 1479 C++11 les opérateurs littéraux pouvaient avoir des arguments par défaut interdit
CWG 2521 C++11 operator "" _Bq était mal formé (aucun diagnostic
requis) car il utilise l'identifiant réservé _Bq
a déprécié la syntaxe d'opérateur littéral
avec espace blanc entre "" et ud-suffix