贝利信息

C++中的用户自定义字面量(User-defined literals)?(为数字或字符串添加后缀)

日期:2026-01-13 00:00 / 作者:穿越時空
用户自定义字面量是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
}

如何定义字符串字面量(如 "abc"_s)?

字符串字面量操作符接收 const char* 和长度 size_t,通常返回一个 constexpr 类型(如自定义 string_view 或编译期字符串类)。注意:普通 std::string 不能用于 constexpr 字符串字面量,因其构造函数非 constexpr(C++20 前)。

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

容易被忽略的限制和陷阱

用户自定义字面量不是万能的“语法糖”:它不改变求值顺序,不参与隐式转换链,也不能重载已有标准后缀(如 _f_z 是保留的);所有自定义后缀必须带下划线前缀(_m 合法,km 非法)。

最常卡住的地方是:想让 "abc"_s 返回 std::string 却忘了 C++17 不支持其 constexpr 构造;或者把 operator""_ms 写成 operator""ms(漏掉下划线),编译直接报错而非警告。