You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17为何允许整数转限定作用域枚举却不支持反向非窄化转换?

C++17限定作用域枚举与整数的双向初始化问题

C++17允许在非窄化转换的前提下,用整数直接初始化限定作用域枚举,示例代码如下:

#include <cstdint>
enum class e16 : uint16_t { x16, y16 };
enum class e32 : uint32_t { x32, y32 };

int main() {
  e32{ uint16_t{} };       // 合法
  e32{ uint32_t{} };       // 合法
  e16{ uint16_t{} };       // 合法
  e16{ uint32_t{} };       // 不允许——窄化转换
}

但为什么不支持反向操作?我知道限定作用域枚举无法隐式转换为整数,但integer{ scoped_enum }属于显式初始化,而且C++已经允许了非窄化的scoped_enum{ integer }转换,按道理下面的代码应该部分合法:

#include <cstdint>
enum class e16 : uint16_t { x16, y16 };
enum class e32 : uint32_t { x32, y32 };

int main() {
  uint16_t{ e16{} };       // 理应合法
  uint16_t{ e32{} };       // 窄化转换(不允许)
  uint32_t{ e16{} };       // 理应合法
  uint32_t{ e32{} };       // 理应合法
}

目前我只能通过static_cast将限定作用域枚举转换为整数,但这种方式会允许不安全的窄化转换。为了避免窄化问题,我写了一个基于SFINAE的模板转换函数:

#include <cstdint>
#include <type_traits>

template<typename INT, typename ENUM, typename = decltype(INT{std::declval<std::underlying_type_t<ENUM>>()})>
inline constexpr INT enum_int_cast(ENUM e) { return static_cast<INT>( e ); }

enum class enum8  : uint8_t  {};
enum class enum16 : uint16_t {};
enum class enum32 : uint32_t {};
enum class enum64 : uint64_t {};

int main() {
   enum_int_cast<uint8_t> ( enum8 {} );    // 合法
   enum_int_cast<uint8_t> ( enum16{} );    // 不允许——窄化转换
   enum_int_cast<uint8_t> ( enum32{} );    // 不允许——窄化转换
   enum_int_cast<uint8_t> ( enum64{} );    // 不允许——窄化转换

   enum_int_cast<uint16_t>( enum8 {} );    // 合法
   enum_int_cast<uint16_t>( enum16{} );    // 合法
   enum_int_cast<uint16_t>( enum32{} );    // 不允许——窄化转换
   enum_int_cast<uint16_t>( enum64{} );    // 不允许——窄化转换

   enum_int_cast<uint32_t>( enum8 {} );    // 合法
   enum_int_cast<uint32_t>( enum16{} );    // 合法
   enum_int_cast<uint32_t>( enum32{} );    // 合法
   enum_int_cast<uint32_t>( enum64{} );    // 不允许——窄化转换

   enum_int_cast<uint64_t>( enum8 {} );    // 合法
   enum_int_cast<uint64_t>( enum16{} );    // 合法
   enum_int_cast<uint64_t>( enum32{} );    // 合法
   enum_int_cast<uint64_t>( enum64{} );    // 合法
}

我有两个疑问:

  1. 为什么C++17允许scoped_enum{ integer }的非窄化转换,却不允许integer{ scoped_enum }的非窄化转换?
  2. 我知道列表初始化不会调用显式构造函数,这似乎意味着隐式转换无法进行,但这也会排除scoped_enum{ integer }的场景,对此我感到困惑。

内容的提问来源于stack exchange,提问作者leekillough

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 02:47:32