std::is_scoped_enum用于精准识别enum class/struct,C++23标准化,支持if constexpr分支、SFINAE约束及安全提取底层类型,不关心final、constexpr等修饰符。
std::is_scoped_enum 用来区分 enum class 和普通 enum
它只在 C++23 中标准化(此前是 GCC/Clang 的扩展),核心用途是元编程中精准识别“
作用域
枚举”——即
或
,而非传统无作用域的
。这在类型分发、SFINAE 条件选择、序列化策略或 trait 特化时很关键。
配合 if constexpr 实现编译期分支
当需要为不同枚举类型提供差异化行为(比如打印、序列化、哈希计算)时,
可直接用于
分支,避免运行时开销和重载歧义。
→ 返回
→ 返回
→ 返回
作为 SFINAE 或 requires 子句的约束条件
想只接受作用域枚举做模板参数?不能只靠
,因为它对两种枚举都返回
。必须叠加
排除传统 enum。
✅ 编译通过
❌ 约束失败,不参与重载决议
若仅用
,两者都会匹配,可能引发意料外的
隐式转换
或 ADL 冲突
与 std::underlying_type 配合提取底层类型更安全
传统
允许隐式转为整数,而
默认禁止——但元编程中常需取其底层类型做 bit 操作或容器索引。此时先确认是 scoped enum,再取
更可靠:
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
立即学习
“
C++免费学习笔记(深入)
”;
对
返回真实底层类型(如
)
对普通
返回
,触发
编译错误
,防止误用
比直接写
更健壮:后者对非枚举类型直接 SFINAE 失败,但对普通 enum 却合法,容易掩盖设计意图
真正容易被忽略的是:
对带
修饰的
同样返回
,但它不关心是否
、是否含
,也不反映是否有自定义
。它的职责非常窄——只回答“这个类型是不是由
或
定义的”。别指望它帮你判断值语义或可比性。
enum classenum structenumstd::is_scoped_enum_vif constexprtemplate
constexpr auto enum_name() {
if constexpr (std::is_scoped_enum_v) {
return "scoped";
} else if constexpr (std::is_enum_v) {
return "unscoped";
} else {
return "not_enum";
}
} enum class Color { R, G };"scoped"enum Dir { L, R };"unscoped"int"not_enum"std::is_enum_vtruestd::is_scoped_enum_vtemplate
requires std::is_scoped_enum_v
constexpr void process_scoped_enum(E e) { /* ... */ } process_scoped_enum(Color::R)process_scoped_enum(Dir::L)std::is_enum_venumenum classstd::underlying_type_ttemplate
using safe_underlying_t = std::conditional_t<
std::is_scoped_enum_v,
std::underlying_type_t,
void
>; enum classintenumvoidstd::underlying_type_tstd::is_scoped_enumfinalenum classtrueconstexpr[[nodiscard]]operator==enum classenum struct