2015-07-06 115 views
2

这与Are C++ enums signed or unsigned?密切相关。根据JavaMan的回答,enum既不是signed也不是unsigned。但它确实遵循整体促销规则。如何覆盖枚举的积分促销规则?

我与使用enums图书馆工作,然后将其传递到预期大多unsigned类型(如unsigned intsize_t)其他类对象。由于语言的规则,启用-Wsign-conversion警告以努力捕捉合法错误导致数量误报。

规则类创造了一种难以确保类型安全并且能够捕捉到常见错误的情况。这很困难,因为我想避免像static_cast这样的东西在整个代码中洒落。

有没有办法改写enums为具体的signedunsigned类型的语言默认行为? (类似于您可以指定char的方式是有符号的还是无符号的)。


相关,该库是在20世纪90年代编写的,因此它支持一些较老的编译器。如果解决方案甚至可以解决C++ 03和更早的问题,那将是非常好的。

How to guard move constructors for C++03 and C++11?,我知道在实践中没有可靠的方法来检测其他C++语言变体何时生效。在使用-std=c++03-std=c++11进行Clang 3.5测试期间,它的表面平坦下来。

+1

你可以使用C++ 11,你可以修改这个库中的枚举定义? – Praetorian

+0

@Praetorian - 不幸的是,我们不能依赖C++ 11。我们仍然需要支持C++ 03(也可能更早)。好的一面,我可以修改库中的枚举定义。如果需要的话,该图书馆是魏岱的[Crypto ++](http://www.cryptopp.com/)。对不起提早不提供这些信息。 – jww

回答

1

你可以滚你自己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提供的话。

2

C++ 03枚举的基础类型取决于其枚举值的范围,并且它促进其基础类型,而不是int(C++ 98 [conv.prom]§4.5/ 2)。

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

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

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

+0

不得不挠我的头什么“-1u”将导致,这帮助了我:http://brnz.org/hbr/?p=1433 – user2950911

+0

@ user2950911是的,重要的是,'-1u'是一个积极的数。所有的枚举值都需要积极才能正常工作,否则编译器将被迫选择'signed long'或'signed long long',它可以同时拥有'-1u'和正确的负数。 – Potatoswatter