如何覆盖枚举的积分提升规则

How to override integral promotion rule for enum?

本文关键字:规则 枚举 何覆盖 覆盖      更新时间:2023-10-16

这与C++枚举是有符号的还是无符号的密切相关?。根据JavaMan的回答,enum既不是signed也不是unsigned。但它确实遵循了整体晋升规则。

我正在使用一个库,该库使用enums,然后将它们传递给其他主要期望unsigned类型的类对象(如unsigned intsize_t(。由于语言的规则,启用-Wsign-conversion警告以捕捉合法错误会导致大量误报。

该规则造成了一种难以确保类型安全和发现常见错误的情况。这很困难,因为我想避免像static_cast这样的东西在整个代码中随意地散布。

是否有一种方法可以覆盖将enums提升为具体signedunsigned类型的语言默认行为?(类似于指定char有符号或无符号的方式(。


相关的,该库是在20世纪90年代编写的,因此它支持许多较旧的编译器。如果该解决方案甚至能解决C++03问题,甚至可能更早,那就太好了。

从如何保护C++03和C++11的移动构造函数?,我知道在实践中没有可靠的方法来检测其他C++语言变体何时生效。在使用-std=c++03-std=c++11的Clang 3.5测试过程中,它的脸平掉了。

C++03枚举的底层类型取决于其枚举器的值范围,并且它提升为其底层类型,而不是int(C++98[conf.prom]§4.5/2(。

强制枚举表现为unsigned int的肮脏方法是添加一个只有unsigned int才能处理的值。

enum things {
    a, b, c,
    force_unsigned = -1U
};

演示:http://coliru.stacked-crooked.com/a/d3ded108fb5a68bf

您可以滚动自己的enum class:

struct safe_enum {
    enum type {
        value1, value2, value3
    };
    type value;
    operator unsigned int ()
        { return value; }
};
safe_enum foo = safe_enum::value1;
unsigned bar = safe_enum::value2;

不幸的是,这失去了C++03枚举的"无范围"行为,因此这种最佳实践模式将破坏代码库。此外,将enum更改为class将破坏ABI(如果它已作为DLL提供(。