C++11부터 사용자 정의 리터럴(user defined literal)을 만들 수 있다. 그러나 실제로 표준 라이브러리에서 사용자 정의 리터럴을 제공하고 있지 않다가 C++14부터 표준 라이브러리에 사용자 정의 리터럴이 도입되기 시작했다.
예를 들어, 아래 예제의 1.2_w나 u"one"_w와 같은 형태로 사용자가 직접 정의한 리터럴을 사용할 수 있다.
사용자 정의 리터럴은 C++ 언어 차원에서 기본적으로 제공하는 리터럴에 suffix를 붙여서 정의할 수 있다.
애플리케이션 코드에서는 _로 시작하는 suffix를 사용하면 된다.
long double operator "" _w(long double);
std::string operator "" _w(const char16_t*, size_t);
unsigned operator "" _w(const char*);
int main(void) {
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
}
이 코드는 개별 operator들이 선언만 되어 있고 정의되어 있지 않아서 실행가능한 바이너리를 빌드하지 못한다.
실제로 동작하는 가장 간단한 예제는 다음과 같다.
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string str = "hello"s + "world"s;
cout << str << endl;
return 0;
}
C++14 표준 라이브러리에 s라는 suffix로 문자열 리터럴을 정의해두었기 때문에 "hello"s 형태로 사용 가능하다.
helloworld
같은 suffix가 다른 타입의 사용자 정의 리터럴로 사용될 수 있다.
#include <iostream>
#include <chrono>
using namespace std;
int main(void)
{
auto threeSeconds = 3s;
return 0;
}
"hello"s는 string 타입의 리터럴이 되고, 3s는 chrono 타입(여기서는 초 단위)의 리터럴이 된다.
사용자 정의 리터럴의 아주 간단한 예제를 만들어보겠다.
킬로미터와 마일 단위로 표기된 사용자 정의 리터럴을 정의한다.
아래 예제에서 36.7_km과 43.5_mi이 각각 킬로미터와 마일 단위 리터럴에 해당한다.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
const long double km_per_mile = 1.609344L;
long double operator""_km(const long double val) {
return val;
}
long double operator""_mi(const long double val) {
return val * km_per_mile;
}
int main(void)
{
cout << 36.7_km << endl;
cout << 43.5_mi << endl;
return 0;
}
마일 단위 리터럴은 킬로미터로 환산해서 값을 반환하도록 operator를 정의하였다.
36.7
70.0065
이 예제를 확장해서 Distance라는 클래스를 만들어보겠다.
이 클래스는 내부적으로 kilometers라는 변수에 값을 저장하고 사용자 정의 리터럴 연산자를 friend 함수로 정의해서 사용하고 있다.
클래스의 + 연산자도 오버로딩하여 정의하였다.
클래스의 << 연산자도 오버로딩하여 킬로미터 단위로 값을 출력하고 "km"라는 문자열을 덧붙여 출력하도록 하였다.
#include <iostream>
#include <string>
using namespace std;
class Distance {
private:
explicit Distance(long double val) : kilometers(val) {}
friend Distance operator"" _km(long double val);
friend Distance operator"" _mi(long double val);
long double kilometers { 0 };
public:
constexpr static long double km_per_mile = 1.609344L;
long double get_kilometers() const {
return kilometers;
}
Distance operator+(Distance other) {
return Distance(get_kilometers() + other.get_kilometers());
}
};
Distance operator""_km(long double val) {
return Distance(val);
}
Distance operator""_mi(long double val) {
return Distance(val * Distance::km_per_mile);
}
ostream& operator<<(ostream& os, const Distance& d) {
os << d.get_kilometers() << "km";
return os;
}
int main(void)
{
Distance d = 36.0_mi + 42.0_km;
cout << d << endl;
return 0;
}
99.9364km