如何避免C++11中使用枚举初始化结构体vector时的窄化转换错误
报错原因
未指定底层类型的普通枚举默认底层类型为int,你定义的枚举值0xA0000000超过了32位有符号int的正数上限(最大值为0x7FFFFFFF),属于负数范围,隐式转换为uint32_t时会被C++列表初始化的严格窄化检查拦截。这一步检查发生在构造函数参数传递阶段,所以你把转换逻辑写在构造函数内部也不会生效。
方案1:指定枚举的底层类型为uint32_t(最推荐)
从根源解决类型不匹配问题,不需要任何额外转换操作:
#include <iostream> #include <vector> #include <string> // 给枚举指定uint32_t作为底层类型 enum NUMBERS : uint32_t { NUMBERS_ZERO = 0xA0000000, NUMBERS_ONE = 0xA0000001, NUMBERS_TWO = 0xA0000002, NUMBERS_THREE = 0xA0000003, }; struct Person { uint32_t m_id = 0; std::string m_name; Person(uint32_t id, std::string name) : m_id(id), m_name(std::move(name)) {} }; // 直接传枚举值即可,不需要转换 std::vector<Person> PersonList = { {NUMBERS_ZERO, "abc"}, {NUMBERS_ONE, "pqr"}, {NUMBERS_TWO, "xyz"}, {NUMBERS_THREE, "zzz"} }; int main() { for (const auto& it : PersonList) std::cout << it.m_id << " : " << it.m_name << "\n"; return 0; }
方案2:给Person添加枚举类型的重载构造函数
如果不能修改枚举的定义,可以新增构造函数重载直接匹配枚举参数:
struct Person { uint32_t m_id = 0; std::string m_name; Person(uint32_t id, std::string name) : m_id(id), m_name(std::move(name)) {} // 新增接收NUMBERS类型的构造函数,内部完成转换 Person(NUMBERS id, std::string name) : m_id(static_cast<uint32_t>(id)), m_name(std::move(name)) {} }; // 初始化写法完全符合预期 std::vector<Person> PersonList = { {NUMBERS_ZERO, "abc"}, {NUMBERS_ONE, "pqr"}, {NUMBERS_TWO, "xyz"}, {NUMBERS_THREE, "zzz"} };
方案3:封装转换辅助函数
如果既不能改枚举也不能加构造函数,用辅助函数简化转换写法:
// 定义全局辅助转换函数 inline uint32_t to_uint(NUMBERS num) { return static_cast<uint32_t>(num); } std::vector<Person> PersonList = { {to_uint(NUMBERS_ZERO), "abc"}, {to_uint(NUMBERS_ONE), "pqr"}, {to_uint(NUMBERS_TWO), "xyz"}, {to_uint(NUMBERS_THREE), "zzz"} };
内容的提问来源于stack exchange,提问作者Ratnesh
相关产品推荐
相关产品推荐

