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

사용자 정의 접미사를 정의하여 정수, 부동 소수점, 문자 및 문자열 리터럴이 사용자 정의 타입의 객체를 생성할 수 있도록 합니다.

목차

구문

사용자 정의 리터럴은 다음 형태 중 하나의 표현식입니다

decimal-literal ud-suffix (1)
octal-literal ud-suffix (2)
hex-literal ud-suffix (3)
binary-literal ud-suffix (4)
fractional-constant exponent-part  (optional) ud-suffix (5)
digit-sequence exponent-part ud-suffix (6)
character-literal ud-suffix (7)
string-literal ud-suffix (8)
**참고:** 주어진 지침에 따라 HTML 태그, 속성, 태그 내 내용, C++ 관련 용어는 번역하지 않고 원본을 유지했습니다. 번역이 필요한 일반 텍스트가 없으므로 원본 구조를 그대로 유지합니다.
1-4) 사용자 정의 정수 리터럴, 예를 들어 12 _km
5-6) 사용자 정의 부동 소수점 리터럴, 예를 들어 0.5 _Pa
7) 사용자 정의 문자 리터럴, 예를 들어 'c' _X
8) 사용자 정의 문자열 리터럴, 예를 들어 "abd" _L 또는 u "xyz" _M
decimal-literal - 정수 리터럴 에서와 동일, 0이 아닌 십진수 숫자 하나와 그 뒤에 오는 0개 이상의 십진수 숫자들
octal-literal - 정수 리터럴 에서와 동일, 0 하나와 그 뒤에 오는 0개 이상의 팔진수 숫자들
hex-literal - 정수 리터럴 에서와 동일, 0x 또는 0X 뒤에 하나 이상의 십육진수 숫자들
binary-literal - 정수 리터럴 에서와 동일, 0b 또는 0B 뒤에 하나 이상의 이진수 숫자들
digit-sequence - 부동 소수점 리터럴 에서와 동일, 십진수 숫자들의 연속
fractional-constant - 부동 소수점 리터럴 에서와 동일, digit-sequence 뒤에 점( 123 . )이 오거나, 선택적 digit-sequence 뒤에 점과 또 다른 digit-sequence 가 옴 ( 1.0 또는 .12 )
exponent-part - 부동 소수점 리터럴 에서와 동일, 문자 e 또는 문자 E 뒤에 선택적 부호, 그리고 digit-sequence 가 옴
character-literal - 문자 리터럴 에서와 동일
string-literal - 문자열 리터럴 에서와 동일, 원시 문자열 리터럴 포함
ud-suffix - 식별자, 리터럴 연산자 또는 리터럴 연산자 템플릿 선언에 의해 도입됨 ( 아래 참조)

정수 부동소수점 숫자 시퀀스에서, 선택적 구분자 ' 는 임의의 두 숫자 사이에 허용됩니다.

(C++14부터)

토큰이 사용자 정의 리터럴 구문과 일반 리터럴 구문 모두와 일치하는 경우, 해당 토큰은 일반 리터럴로 간주됩니다(즉, LL 123LL 에서 오버로드하는 것은 불가능합니다).

컴파일러가 사용자 정의 리터럴을 ud-suffix X 와 함께 만나면, 비정규 이름 조회 를 수행하여 operator "" X 라는 이름의 함수를 찾습니다. 조회가 선언을 찾지 못하면 프로그램은 잘못된 형식입니다. 그렇지 않은 경우,

1) 사용자 정의 정수 리터럴의 경우,
a) 오버로드 집합에 매개변수 타입이 unsigned long long 인 리터럴 연산자가 포함된 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X ( n  ULL ) 로 처리되며, 여기서 n ud-suffix 가 없는 리터럴입니다;
b) 그렇지 않은 경우, 오버로드 집합은 원시 리터럴 연산자 또는 숫자 리터럴 연산자 템플릿 중 하나를 포함해야 하지만 둘 다를 포함해서는 안 됩니다. 오버로드 집합에 원시 리터럴 연산자가 포함된 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X ( " n  ") 로 처리됩니다;
c) 그렇지 않고, 오버로드 집합에 숫자 리터럴 연산자 템플릿이 포함된 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X < ' c1  ' , ' c2  ' , ' c3  ' ..., ' ck  ' > ( ) 로 처리되며, 여기서 c1 .. ck n 의 개별 문자들이고, 이들 모두가 기본 문자 집합 에 속합니다.
2) 사용자 정의 부동 소수점 리터럴의 경우,
a) 오버로드 집합에 매개변수 타입이 long double 인 리터럴 연산자가 포함된 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X ( f   L ) 로 처리되며, 여기서 f ud-suffix 가 제거된 리터럴입니다;
b) 그렇지 않은 경우, 오버로드 집합은 원시 리터럴 연산자 또는 숫자 리터럴 연산자 템플릿 중 하나를 포함해야 하지만 둘 다를 포함해서는 안 됩니다. 오버로드 집합에 원시 리터럴 연산자가 포함된 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X ( " f   ") ;로 처리됩니다.
c) 그렇지 않고, 오버로드 집합에 숫자 리터럴 연산자 템플릿이 포함된 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X < ' c1  ' , ' c2  ' , ' c3  ' ..., ' ck  ' > ( ) 로 처리되며, 여기서 c1 .. ck f 의 개별 문자들이고 이들 모두가 기본 문자 집합 에 속합니다.
3) 사용자 정의 문자열 리터럴의 경우, str ud-suffix 가 없는 리터럴로 둡니다:
a) 오버로드 집합에 str 이 올바른 템플릿 인자로 사용되는 상수 템플릿 매개변수를 가진 문자열 리터럴 연산자 템플릿이 포함된 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X < str > ( ) 로 처리됩니다;
(since C++20)
b) 그렇지 않은 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X ( str, len ) 로 처리되며, 여기서 len 은 널 종결 문자를 제외한 문자열 리터럴의 길이입니다.
4) 사용자 정의 문자 리터럴의 경우, 사용자 정의 리터럴 표현식은 함수 호출 operator "" X ( ch ) 로 처리되며, 여기서 ch 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;    // operator ""_w(1.2L) 호출
    u"one"_w; // operator ""_w(u"one", 3) 호출
    12_w;     // operator ""_w("12") 호출
    "two"_w;  // 오류: 적용 가능한 리터럴 연산자가 없음
}

문자열 리터럴 연결이 번역 단계 6 에서 발생할 때, 사용자 정의 문자열 리터럴들도 함께 연결되며, 연결된 리터럴들 전체에 단 하나의 접미사만 나타날 수 있다는 점을 제외하고는 연결 목적상 그들의 ud-suffix 들은 무시됩니다:

int main()
{
    L"A" "B" "C"_x;  // OK: L"ABC"_x와 동일함
    "P"_x "Q" "R"_y; // 오류: 두 개의 다른 사용자 정의 접미사(_x와 _y)
}

리터럴 연산자

사용자 정의 리터럴에 의해 호출되는 함수는 literal operator (또는 템플릿인 경우 literal operator template )로 알려져 있습니다. 이는 네임스페이스 범위에서 다른 function 또는 function template 와 마찬가지로 선언됩니다(이는 friend function, 함수 템플릿의 명시적 인스턴스화 또는 특수화, 혹은 using-declaration에 의해 도입될 수도 있습니다). 단, 다음과 같은 제한 사항이 적용됩니다:

이 함수의 이름은 두 가지 형태 중 하나를 가질 수 있습니다:

operator "" identifier (1) (사용 중단됨)
operator user-defined-string-literal (2)
identifier - 이 함수를 호출할 사용자 정의 리터럴의 ud-suffix 로 사용할 identifier
user-defined-string-literal - "" 문자 시퀀스 뒤에 공백 없이 이어지는, ud-suffix 가 되는 문자 시퀀스
1) 리터럴 연산자를 선언합니다.
2) 리터럴 연산자를 선언합니다. 이 구문을 사용하면 언어 키워드와 예약된 식별자 ud-suffix 로 사용할 수 있습니다. 예를 들어 operator "" if 와 같은 구문이 <complex> 헤더에서 사용됩니다.

ud-suffix 는 밑줄 _ 로 시작해야 합니다: 밑줄로 시작하지 않는 접미사는 표준 라이브러리에서 제공하는 리터럴 연산자를 위해 예약되어 있습니다. 또한 이중 밑줄 __ 을 포함할 수 없습니다: 이러한 접미사 역시 예약되어 있습니다.

리터럴 연산자가 템플릿인 경우, 빈 매개변수 목록을 가져야 하며 하나의 템플릿 매개변수만 가질 수 있습니다. 이 매개변수는 요소 타입이 char 인 상수 템플릿 매개변수 팩이어야 합니다 (이 경우 numeric literal operator template 으로 알려져 있습니다):

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

또는 클래스 타입의 상수 템플릿 매개변수인 경우(이 경우 문자열 리터럴 연산자 템플릿 으로 알려져 있음):

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

리터럴 연산자에는 다음 매개변수 목록만 허용됩니다:

( const char * ) (1)
( unsigned long long int ) (2)
( long double ) (3)
( char ) (4)
( wchar_t ) (5)
( char8_t ) (6) (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) (C++20부터)
( const char16_t * , std::size_t ) (12)
( const char32_t * , std::size_t ) (13)
1) 이 매개변수 목록을 가진 리터럴 연산자는 원시 리터럴 연산자 로, 정수 및 부동 소수점 사용자 정의 리터럴을 위한 폴백으로 사용됩니다 (위 참조)
2) 이러한 매개변수 목록을 가진 리터럴 연산자는 사용자 정의 정수 리터럴에 대한 최우선 리터럴 연산자입니다
3) 이러한 매개변수 목록을 가진 리터럴 연산자는 사용자 정의 부동 소수점 리터럴에 대한 최우선 리터럴 연산자입니다
4-8) 이러한 매개변수 목록을 가진 리터럴 연산자는 사용자 정의 문자 리터럴에 의해 호출됩니다
9-13) 이러한 매개변수 목록을 가진 리터럴 연산자는 사용자 정의 문자열 리터럴에 의해 호출됩니다

기본 인수 는 허용되지 않습니다.

C language linkage 는 허용되지 않습니다.

위의 제한 사항을 제외하면, 리터럴 연산자와 리터럴 연산자 템플릿은 일반 함수(및 함수 템플릿)이며, inline이나 constexpr로 선언될 수 있고, 내부 또는 외부 링크를 가질 수 있으며, 명시적으로 호출될 수 있고, 주소를 취할 수 있습니다 등.

#include <string>
void        operator ""_km(long double); // OK, 1.0_km에 대해 호출됨
void        operator "" _km(long double); // 위와 동일, 사용 권장되지 않음
std::string operator ""_i18n(const char*, std::size_t); // OK
template<char...>
double operator ""_pi(); // OK
float  operator ""_e(const char*); // OK
// 오류: 접미사는 밑줄로 시작해야 함
float operator ""Z(const char*);
// 오류: 밑줄로 시작하고 대문자가 뒤따르는 모든 이름은 예약됨
// (참고: ""와 _ 사이에 공백이 있음)
double operator"" _Z(long double);
// OK. 참고: ""와 _ 사이에 공백 없음
double operator""_Z(long double);
// OK: 리터럴 연산자는 오버로드 가능
double operator ""_Z(const char* args);
int main() {}

참고 사항

사용자 정의 리터럴이 도입된 이후, 앞선 문자열 리터럴 뒤에 공백 없이 고정 너비 정수 타입에 대한 형식 매크로 상수 를 사용하는 코드는 유효하지 않게 되었습니다: std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; 는 다음으로 대체되어야 합니다: std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; .

최대한 많이 인식(maximal munch) 규칙으로 인해, p , P , (C++17부터) e E 로 끝나는 사용자 정의 정수 및 부동 소수점 리터럴은 + 또는 - 연산자가 뒤따를 경우, 소스 코드에서 공백이나 괄호로 연산자와 분리해야 합니다:

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;   // 오류
auto y = 1.0_a+2.0;   // 정상
auto z = 1.0_E +2.0;  // 정상
auto q = (1.0_E)+2.0; // 정상
auto w = 1_p+2;       // 오류
auto u = 1_p +2;      // 정상

정수나 부동소수점 사용자 정의 리터럴 뒤에 오는 점 연산자에도 동일하게 적용됩니다:

#include <chrono>
using namespace std::literals;
auto a = 4s.count();   // 오류
auto b = 4s .count();  // 정상
auto c = (4s).count(); // 정상

그렇지 않으면 단일 유효하지 않은 전처리 숫자 토큰(예: 1.0 _E + 2.0 또는 4s. count )이 생성되어 컴파일이 실패하게 됩니다.

기능 테스트 매크로 표준 기능
__cpp_user_defined_literals 200809L (C++11) 사용자 정의 리터럴

키워드

operator

예제

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <numbers>
#include <string>
// 입력 파라미터인 도(degrees)를 라디안(radians)으로 변환하는 용도
constexpr long double operator""_deg_to_rad(long double deg)
{
    long double radians = deg * std::numbers::pi_v<long double> / 180;
    return radians;
}
// 사용자 정의 타입과 함께 사용
struct mytype
{
    unsigned long long m;
};
constexpr mytype operator""_mytype(unsigned long long n)
{
    return mytype{n};
}
// 부수 효과(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 문자열 리터럴 연산자 템플릿
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';
}

출력:

1.570796
123
0x123ABC
abcabc

표준 라이브러리

다음 리터럴 연산자들은 표준 라이브러리에 정의되어 있습니다:

인라인 네임스페이스에 정의됨 std::literals::complex_literals
순수 허수를 나타내는 std::complex 리터럴
(함수)
인라인 네임스페이스에 정의됨 std::literals::chrono_literals
시간을 나타내는 std::chrono::duration 리터럴
(함수)
분을 나타내는 std::chrono::duration 리터럴
(함수)
초를 나타내는 std::chrono::duration 리터럴
(함수)
밀리초를 나타내는 std::chrono::duration 리터럴
(함수)
마이크로초를 나타내는 std::chrono::duration 리터럴
(함수)
나노초를 나타내는 std::chrono::duration 리터럴
(함수)
특정 연도를 나타내는 std::chrono::year 리터럴
(함수)
월의 특정 날짜를 나타내는 std::chrono::day 리터럴
(함수)
인라인 네임스페이스에 정의됨 std::literals::string_literals
문자 배열 리터럴을 basic_string 으로 변환
(함수)
인라인 네임스페이스에 정의됨 std::literals::string_view_literals
문자 배열 리터럴의 string view를 생성
(함수)

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 1473 C++11 리터럴 연산자 선언에서 "" ud-suffix 사이의 공백이
필요했음
선택적으로 변경됨
CWG 1479 C++11 리터럴 연산자가 기본 인수를 가질 수 있었음 금지됨
CWG 2521 C++11 operator "" _Bq 는 잘못된 형식이었음 (진단 불필요)
예약된 식별자 _Bq 를 사용하기 때문
"" ud-suffix 사이에 공백이 있는
리터럴 연산자 구문을 사용하지 않도록 변경됨