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{} ); // 合法 }
我有两个疑问:
- 为什么C++17允许
scoped_enum{ integer }的非窄化转换,却不允许integer{ scoped_enum }的非窄化转换? - 我知道列表初始化不会调用显式构造函数,这似乎意味着隐式转换无法进行,但这也会排除
scoped_enum{ integer }的场景,对此我感到困惑。
内容的提问来源于stack exchange,提问作者leekillough
相关产品推荐
相关产品推荐

