Skip to main content

User-defined literals (since C++11)

Allows integer, floating-point, character, and string literals to produce objects of user-defined type by defining a user-defined suffix.

Syntax

A user-defined literal is an expression of any of the following forms

1
decimal-literalud-suffix
2
octal-literalud-suffix
3
hex-literalud-suffix
4
binary-literalud-suffix
5
fractional-constantexponent-part(optional)ud-suffix
6
digit-sequenceexponent-partud-suffix
7
character-literalud-suffix
8
string-literalud-suffix
pubdecimal-literalsame as in integer literal, a non-zero decimal digit followed by zero or more decimal digits
puboctal-literalsame as in integer literal, a zero followed by zero or more octal digits
pubhex-literalsame as in integer literal, 0x or 0X followed by one or more hexadecimal digits
pubbinary-literalsame as in integer literal, 0b or 0B followed by one or more binary digits
pubdigit-sequencesame as in floating literal, a sequence of decimal digits
pubfractional-constantsame as in floating literal, either a digit-sequence followed by a dot (123.) or an optional digit-sequence followed by a dot and another digit-sequence
(1.0 or .12)
pubexponent-partsame as in floating literal, the letter e or the letter E followed by optional sign, followed by digit-sequence
pubcharacter-literalsame as in character literal
pubstring-literalsame as in string literal, including raw string literals
pubud-suffixan identifier, introduced by a literal operator or a literal operator template declaration (see below)
In the integer and floating-point digit sequences, optional separators ' are allowed between any two digits. (since C++14)

If a token matches a user-defined literal syntax and a regular literal syntax, it is assumed to be a regular literal (that is, it's impossible to overload LL in 123LL).

When the compiler encounters a user-defined literal with ud-suffix X, it performs unqualified name lookup, looking for a function with the name operator""X. If the lookup does not find a declaration, the program is ill-formed. Otherwise,

  1. For user-defined integer literals,
    1. if the overload set includes a literal operator with the parameter type unsigned long long, the user-defined literal expression is treated as a function call operator ""X(nULL), where n is the literal without ud-suffix;
    2. otherwise, the overload set must include either, but not both, a raw literal operator or a numeric literal operator template. If the overload set includes a raw literal operator, the user-defined literal expression is treated as a function call operator ""X("n");
    3. otherwise, if the overload set includes a numeric literal operator template, the user-defined literal expression is treated as a function call operator ""X(>'c1', 'c2', 'c3'..., 'ck'<()), where c1..ck are the individual characters of n and all of them are from the basic character set.
  2. For user-defined floating-point literals,
    1. If the overload set includes a literal operator with the parameter type long double, the user-defined literal expression is treated as a function call operator ""X(fL), where f is the literal without ud-suffix;
    2. otherwise, the overload set must include either, but not both, a raw literal operator or a numeric literal operator template. If the overload set includes a raw literal operator, the user-defined literal expression is treated as a function call operator ""X("f");
    3. otherwise, if the overload set includes a numeric literal operator template, the user-defined literal expression is treated as a function calloperator ""X(>'c1', 'c2', 'c3'..., 'ck'<()), where c1..ck are the individual characters of f and all of them are from the basic character set.
  3. For user-defined string literals, let str be the literal without ud-suffix:
    1. If the overload set includes a string literal operator template with a non-type template parameter for which str is a well-formed template argument, then the user-defined literal expression is treated as a function call operator ""X<str>(); (since C++20)
    2. otherwise, the user-defined literal expression is treated as a function call operator ""X (str, len), where len is the length of the string literal, excluding the terminating null character.
  4. For user-defined character literals, the user-defined literal expression is treated as a function call operator ""X (ch), where ch is the literal without ud-suffix.
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
}

When string literal concatenation takes place in translation phase 6, user-defined string literals are concatenated as well, and their ud-suffixes are ignored for the purpose of concatenation, except that only one suffix may appear on all concatenated literals:

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)
}

Literal operators

The function called by a user-defined literal is known as literal operator (or, if it's a template, literal operator template). It is declared just like any other function or function template at namespace scope (it may also be a friend function, an explicit instantiation or specialization of a function template, or introduced by a using-declaration), except for the following restrictions:

The name of this function can have one of the two forms:

1operator ""
identifier (deprecated)
2operator
user-defined-string-literal
pubidentifierthe identifier to use as the ud-suffix for the user-defined literals that will call this function
pubuser-defined-string-literalthe character sequence " " followed, without a space, by the character sequence that becomes the ud-suffix
  1. Declares a literal operator.
  2. Declares a literal operator. This syntax makes it possible to use language keywords and reserved identifiers as ud-suffixes, for example, operator ""if from the header <complex>.

 
ud-suffix must begin with the underscore _: the suffixes that do not begin with the underscore are reserved for the literal operators provided by the standard library. It cannot contain double underscores __ as well: such suffixes are also reserved.

If the literal operator is a template, it must have an empty parameter list and can have only one template parameter, which must be a non-type template parameter pack with element type char (in which case it is known as a numeric literal operator template):

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

or a non-type template parameter of class type (in which case it is known as a string literal operator template):

struct A { constexpr A(const char*); };

template<A a>
A operator ""_a();
 (since C++23)

Only the following parameter lists are allowed on literal operators:

1
( const char* )
2
( unsigned long long int )
3
( long double )
4
( char )
5
( wchar_t )
6
( char8_t ) (since C++20)
7
( char16_t )
8
( char32_t )
9
( const char*, std::size_t )
10
( const wchar_t*, std::size_t )
11
( const char8_t*, std::size_t ) (since C++20)
12
( const char16_t*, std::size_t )
13
( const char32_t*, std::size_t )
    1. Literal operators with this parameter list are the raw literal operators, used as fallbacks for integer and floating-point user-defined literals (see above)
    1. Literal operators with these parameter lists are the first-choice literal operator for user-defined integer literals
    1. Literal operators with these parameter lists are the first-choice literal operator for user-defined floating-point literals
  • 4-8) Literal operators with these parameter lists are called by user-defined character literals
  • 9-13) Literal operators with these parameter lists are called by user-defined string literals

Default arguments are not allowed.
C language linkage is not allowed.

Other than the restrictions above, literal operators and literal operator templates are normal functions (and function templates), they can be declared inline or constexpr, they may have internal or external linkage, they can be called explicitly, their addresses can be taken, etc.

#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 ""(); // 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() {}

Since the introduction of user-defined literals, the code that uses format macro constants for fixed-width integer types with no space after the preceding string literal became invalid: std::printf("%"PRId64"\n",INT64_MIN); has to be replaced by std::printf("%" PRId64"\n",INT64_MIN);.

Due to maximal munch, user-defined integer and floating point literals ending in p, P (since C++17), e and E, when followed by the operators + or -, must be separated from the operator with whitespace or parentheses in the 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; // 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

Same applies to dot operator following an integer or floating-point user-defined literal:

#include <chrono>

using namespace std::literals;

auto a = 4s.count(); // Error
auto b = 4s .count(); // OK
auto c = (4s).count(); // OK

Otherwise, a single invalid preprocessing number token (e.g., 1.0_E+2.0 or 4s.count) is formed, which causes compilation to fail.

Feature-test macroValueStdComment
__cpp_user_defined_literals200809L(C++11)User-defined literals

Example

#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';
}
Result
1.570796
123
0x123ABC
abcabc

Standard library

The following literal operators are defined in the standard library:

Defined in inline namespace std::literals::complex_literals
puboperator""if
operator""i
operator""il
 (since C++14)
a std::complex literal representing purely imaginary number
Defined in inline namespace std::literals::chrono_literals
puboperator""h (since C++14)a std::chrono::duration literal representing hours
puboperator""min (since C++14)a std::chrono::duration literal representing minutes
puboperator""s (since C++14)a std::chrono::duration literal representing seconds
puboperator""ms (since C++14)a std::chrono::duration literal representing miliseconds
puboperator""us (since C++14)a std::chrono::duration literal representing microseconds
puboperator""ns (since C++14)a std::chrono::duration literal representing nanoseconds
puboperator""y (since C++20)a std::chrono::year literal representing a particular year
puboperator""d (since C++20)a std::chrono::day literal representing a day of the month
Defined in inline namespace std::literals::string_literals
puboperator""s (since C++14)converts a character array literal to basic_string
Defined in inline namespace std::literals::string_view_literals
puboperator""sv (since C++17)creates a string view of a character array literal

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DRApplied toBehavior as publishedCorrect behavior
CWG 1473(C++11)whitespace between " " and ud-suffix was required in the declaration of literal operatorsmade optional
CWG 1479(C++11)literal operators could have default argumentsprohibited
CWG 2521(C++11)operator" " _Bq was ill-formed (no diagnostic required) because it uses the reserved identifier _Bqdeprecated the literal operator syntax with whitespace between " " and ud-suffix

User-defined literals (since C++11)

Allows integer, floating-point, character, and string literals to produce objects of user-defined type by defining a user-defined suffix.

Syntax

A user-defined literal is an expression of any of the following forms

1
decimal-literalud-suffix
2
octal-literalud-suffix
3
hex-literalud-suffix
4
binary-literalud-suffix
5
fractional-constantexponent-part(optional)ud-suffix
6
digit-sequenceexponent-partud-suffix
7
character-literalud-suffix
8
string-literalud-suffix
pubdecimal-literalsame as in integer literal, a non-zero decimal digit followed by zero or more decimal digits
puboctal-literalsame as in integer literal, a zero followed by zero or more octal digits
pubhex-literalsame as in integer literal, 0x or 0X followed by one or more hexadecimal digits
pubbinary-literalsame as in integer literal, 0b or 0B followed by one or more binary digits
pubdigit-sequencesame as in floating literal, a sequence of decimal digits
pubfractional-constantsame as in floating literal, either a digit-sequence followed by a dot (123.) or an optional digit-sequence followed by a dot and another digit-sequence
(1.0 or .12)
pubexponent-partsame as in floating literal, the letter e or the letter E followed by optional sign, followed by digit-sequence
pubcharacter-literalsame as in character literal
pubstring-literalsame as in string literal, including raw string literals
pubud-suffixan identifier, introduced by a literal operator or a literal operator template declaration (see below)
In the integer and floating-point digit sequences, optional separators ' are allowed between any two digits. (since C++14)

If a token matches a user-defined literal syntax and a regular literal syntax, it is assumed to be a regular literal (that is, it's impossible to overload LL in 123LL).

When the compiler encounters a user-defined literal with ud-suffix X, it performs unqualified name lookup, looking for a function with the name operator""X. If the lookup does not find a declaration, the program is ill-formed. Otherwise,

  1. For user-defined integer literals,
    1. if the overload set includes a literal operator with the parameter type unsigned long long, the user-defined literal expression is treated as a function call operator ""X(nULL), where n is the literal without ud-suffix;
    2. otherwise, the overload set must include either, but not both, a raw literal operator or a numeric literal operator template. If the overload set includes a raw literal operator, the user-defined literal expression is treated as a function call operator ""X("n");
    3. otherwise, if the overload set includes a numeric literal operator template, the user-defined literal expression is treated as a function call operator ""X(>'c1', 'c2', 'c3'..., 'ck'<()), where c1..ck are the individual characters of n and all of them are from the basic character set.
  2. For user-defined floating-point literals,
    1. If the overload set includes a literal operator with the parameter type long double, the user-defined literal expression is treated as a function call operator ""X(fL), where f is the literal without ud-suffix;
    2. otherwise, the overload set must include either, but not both, a raw literal operator or a numeric literal operator template. If the overload set includes a raw literal operator, the user-defined literal expression is treated as a function call operator ""X("f");
    3. otherwise, if the overload set includes a numeric literal operator template, the user-defined literal expression is treated as a function calloperator ""X(>'c1', 'c2', 'c3'..., 'ck'<()), where c1..ck are the individual characters of f and all of them are from the basic character set.
  3. For user-defined string literals, let str be the literal without ud-suffix:
    1. If the overload set includes a string literal operator template with a non-type template parameter for which str is a well-formed template argument, then the user-defined literal expression is treated as a function call operator ""X<str>(); (since C++20)
    2. otherwise, the user-defined literal expression is treated as a function call operator ""X (str, len), where len is the length of the string literal, excluding the terminating null character.
  4. For user-defined character literals, the user-defined literal expression is treated as a function call operator ""X (ch), where ch is the literal without ud-suffix.
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
}

When string literal concatenation takes place in translation phase 6, user-defined string literals are concatenated as well, and their ud-suffixes are ignored for the purpose of concatenation, except that only one suffix may appear on all concatenated literals:

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)
}

Literal operators

The function called by a user-defined literal is known as literal operator (or, if it's a template, literal operator template). It is declared just like any other function or function template at namespace scope (it may also be a friend function, an explicit instantiation or specialization of a function template, or introduced by a using-declaration), except for the following restrictions:

The name of this function can have one of the two forms:

1operator ""
identifier (deprecated)
2operator
user-defined-string-literal
pubidentifierthe identifier to use as the ud-suffix for the user-defined literals that will call this function
pubuser-defined-string-literalthe character sequence " " followed, without a space, by the character sequence that becomes the ud-suffix
  1. Declares a literal operator.
  2. Declares a literal operator. This syntax makes it possible to use language keywords and reserved identifiers as ud-suffixes, for example, operator ""if from the header <complex>.

 
ud-suffix must begin with the underscore _: the suffixes that do not begin with the underscore are reserved for the literal operators provided by the standard library. It cannot contain double underscores __ as well: such suffixes are also reserved.

If the literal operator is a template, it must have an empty parameter list and can have only one template parameter, which must be a non-type template parameter pack with element type char (in which case it is known as a numeric literal operator template):

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

or a non-type template parameter of class type (in which case it is known as a string literal operator template):

struct A { constexpr A(const char*); };

template<A a>
A operator ""_a();
 (since C++23)

Only the following parameter lists are allowed on literal operators:

1
( const char* )
2
( unsigned long long int )
3
( long double )
4
( char )
5
( wchar_t )
6
( char8_t ) (since C++20)
7
( char16_t )
8
( char32_t )
9
( const char*, std::size_t )
10
( const wchar_t*, std::size_t )
11
( const char8_t*, std::size_t ) (since C++20)
12
( const char16_t*, std::size_t )
13
( const char32_t*, std::size_t )
    1. Literal operators with this parameter list are the raw literal operators, used as fallbacks for integer and floating-point user-defined literals (see above)
    1. Literal operators with these parameter lists are the first-choice literal operator for user-defined integer literals
    1. Literal operators with these parameter lists are the first-choice literal operator for user-defined floating-point literals
  • 4-8) Literal operators with these parameter lists are called by user-defined character literals
  • 9-13) Literal operators with these parameter lists are called by user-defined string literals

Default arguments are not allowed.
C language linkage is not allowed.

Other than the restrictions above, literal operators and literal operator templates are normal functions (and function templates), they can be declared inline or constexpr, they may have internal or external linkage, they can be called explicitly, their addresses can be taken, etc.

#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 ""(); // 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() {}

Since the introduction of user-defined literals, the code that uses format macro constants for fixed-width integer types with no space after the preceding string literal became invalid: std::printf("%"PRId64"\n",INT64_MIN); has to be replaced by std::printf("%" PRId64"\n",INT64_MIN);.

Due to maximal munch, user-defined integer and floating point literals ending in p, P (since C++17), e and E, when followed by the operators + or -, must be separated from the operator with whitespace or parentheses in the 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; // 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

Same applies to dot operator following an integer or floating-point user-defined literal:

#include <chrono>

using namespace std::literals;

auto a = 4s.count(); // Error
auto b = 4s .count(); // OK
auto c = (4s).count(); // OK

Otherwise, a single invalid preprocessing number token (e.g., 1.0_E+2.0 or 4s.count) is formed, which causes compilation to fail.

Feature-test macroValueStdComment
__cpp_user_defined_literals200809L(C++11)User-defined literals

Example

#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';
}
Result
1.570796
123
0x123ABC
abcabc

Standard library

The following literal operators are defined in the standard library:

Defined in inline namespace std::literals::complex_literals
puboperator""if
operator""i
operator""il
 (since C++14)
a std::complex literal representing purely imaginary number
Defined in inline namespace std::literals::chrono_literals
puboperator""h (since C++14)a std::chrono::duration literal representing hours
puboperator""min (since C++14)a std::chrono::duration literal representing minutes
puboperator""s (since C++14)a std::chrono::duration literal representing seconds
puboperator""ms (since C++14)a std::chrono::duration literal representing miliseconds
puboperator""us (since C++14)a std::chrono::duration literal representing microseconds
puboperator""ns (since C++14)a std::chrono::duration literal representing nanoseconds
puboperator""y (since C++20)a std::chrono::year literal representing a particular year
puboperator""d (since C++20)a std::chrono::day literal representing a day of the month
Defined in inline namespace std::literals::string_literals
puboperator""s (since C++14)converts a character array literal to basic_string
Defined in inline namespace std::literals::string_view_literals
puboperator""sv (since C++17)creates a string view of a character array literal

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DRApplied toBehavior as publishedCorrect behavior
CWG 1473(C++11)whitespace between " " and ud-suffix was required in the declaration of literal operatorsmade optional
CWG 1479(C++11)literal operators could have default argumentsprohibited
CWG 2521(C++11)operator" " _Bq was ill-formed (no diagnostic required) because it uses the reserved identifier _Bqdeprecated the literal operator syntax with whitespace between " " and ud-suffix