C++26:Std:Is_within_lifetime
Source: Hacker News
std::is_within_lifetime 是做什么的?
C++26 添加了
bool std::is_within_lifetime(const T* p);
到 “ 头文件中。该函数在常量求值期间检查 p 是否指向当前仍在其生命周期内的对象。
最常见的用例是检查联合体的哪个成员是活动的:
union Storage {
int i;
double d;
};
constexpr bool check_active_member() {
Storage s;
s.i = 42; // `i` 成为活动成员
return std::is_within_lifetime(&s.i); // true
// std::is_within_lifetime(&s.d) 在这里会返回 false
}
特性与命名
只支持 consteval
std::is_within_lifetime 是 consteval 的,因此只能在编译期求值时使用。运行时通常需要通过额外的状态来跟踪活动成员;编译器在常量求值之外并不会保留相同的生命周期跟踪信息。
为什么使用指针而不是引用?
函数接受指针而不是引用,以避免临时对象和生命周期延长规则带来的复杂性。指针可以明确表明你正在查询的具体内存位置。
为什么不叫 “is_union_member_active”?
委员会选择了更通用的名称,因为该机制的用途可以超出联合体。它提供了一种在常量求值中查询对象生命周期的通用方式,未来可能会有更多的应用场景。
最初的动机
该提案源于一个具体问题:实现一个占用最小存储空间的 Optional。考虑一种类型,它要么存储一个 bool 值,要么什么都不存,用联合体来节省空间:
struct OptBool {
union { bool b; char c; };
constexpr auto has_value() const -> bool {
// 如何判断 `b` 是活动成员?
// 当 `c` 为活动成员时读取 `b` 是未定义行为。
}
};
在运行时可以使用 c 的哨兵值(例如 2)来表示 “无值”。然而在常量求值期间,需要一种不依赖此类技巧的方法来检测活动成员。std::is_within_lifetime 解决了这个问题:
struct OptBool {
union { bool b; char c; };
constexpr auto has_value() const -> bool {
if consteval {
return std::is_within_lifetime(&b);
} else {
return c != 2; // 运行时的哨兵值
}
}
constexpr bool value() const {
return b;
}
};
在 constexpr 环境下,该函数告诉我们 b 当前是否存活;在运行时我们回退到哨兵检查。
编译器支持
截至 2026 年 2 月,尚无主流编译器实现 std::is_within_lifetime。随着 C++26 实现的成熟,支持将会逐步到来。
结论
C++26 的 std::is_within_lifetime 提供了一个专注于 constexpr 的工具,用于查询对象生命周期,主要用于在不触发未定义行为的前提下确定联合体的活动成员。其设计——指针参数、consteval 限制以及通用名称——在满足当前需求的同时也为未来的可扩展性留下了余地,使得常量求值更加实用且富有表现力。