用户自定义字面量是C++11引入的编译期类型安全扩展机制,通过operator””_xxx constexpr函数为字面量添加后缀(如123_km、”hello”_s),支持数值(参数为unsigned long long或long double)和字符串(const char*+size_t)形式,后缀须以下划线开头且全局定义。

什么是用户自定义字面量?
用户自定义字面量是 C++11 引入的语法机制,允许你为数字、字符串、字符等字面量添加后缀(如 123_km、"hello"_s),并由你定义的函数处理其含义。它不是宏或模板元编程的替代品,而是一种编译期可解析、类型安全的轻量扩展方式。
如何定义数值型字面量(如 123.5_m)?
必须定义为 constexpr 函数,且函数名形如 operator""_xxx,参数类型取决于字面量形式:整数用 unsigned long long,浮点数用 long double,字符串用 const char* + size_t。
常见错误:用 double 作参数——编译器只接受 long double;或忘记 constexpr 导致无法用于编译期常量上下文(如数组长度、模板非类型参数)。
constexpr double operator""_m(long double val) {
return static_cast(val) * 1.0; // 1 米 = 1.0 米(可加换算)
}
constexpr int operator""_km(unsigned long long val) {
return static_cast(val * 1000); // 1 km → 1000 m
}
-
1.5_m调用operator""_m(1.5L) -
2_km调用operator""_km(2ULL) - 后缀名必须以字母开头(
_1m非法,_m1合法)
如何定义字符串字面量(如 "abc"_s)?
字符串字面量操作符接收 const char* 和长度 size_t,通常返回一个 constexpr 类型(如自定义 string_view 或编译期字符串类)。注意:普通 std::string 不能用于 constexpr 字符串字面量,因其构造函数非 constexpr(C++20 前)。
立即学习“C++免费学习笔记(深入)”;
struct const_string {
const char* data;
size_t len;
constexpr const_string(const char* s, size_t n) : data(s), len(n) {}
};
constexpr const_string operator""_s(const char* s, size_t n) {
return const_string{s, n};
}
-
"hello"_s生成一个编译期已知的const_string - 不能在函数体内对
s做strlen或其它运行时计算——s是字面量地址,但内容不可修改,且长度由编译器传入 - C++20 起可用
std::string_view直接作为返回类型:constexpr std::string_view operator""_sv(const char* s, size_t n)
容易被忽略的限制和陷阱
用户自定义字面量不是万能的“语法糖”:它不改变求值顺序,不参与隐式转换链,也不能重载已有标准后缀(如 _f、_z 是保留的);所有自定义后缀必须带下划线前缀(_m 合法,km 非法)。
- 全局作用域定义的操作符才能被常规使用;放在命名空间内需显式引入(
using namespace ns;) - 多个同名后缀(如不同命名空间里的
operator""_s)会导致 ODR 违规,链接失败 - 字符串字面量操作符不能接受 UTF-8/16/32 原生字面量(
u8"..."_s会触发const char8_t*版本,需单独定义)
最常卡住的地方是:想让 "abc"_s 返回 std::string 却忘了 C++17 不支持其 constexpr 构造;或者把 operator""_ms 写成 operator""ms(漏掉下划线),编译直接报错而非警告。
