【发布时间】:2016-09-12 17:03:55
【问题描述】:
给定enum class val { foo = 1, bar = 2, baz = 4 };
可以定义:
val operator|(val x, val y)
{
return static_cast<val>(static_cast<int>(x) | static_cast<int>(y));
}
但是,这样做在语义上是否正确?
我倾向于不,如下面的看似良好的示例所示:
int convert(val x)
{
switch(x)
{
case val::foo: return 42;
case val::bar: return 53;
case val::baz: return 64;
}
}
当使用 g++ 编译并且使用 clang++ 进行分段错误时,调用 convert(val::foo | val::bar) 将返回 0。
Here 是 g++ 版本。而here是clang++版本。
我的问题有两个:
- 在枚举中存储不由枚举器表示的值在语义上是否正确?我们非常欢迎标准摘录。
1.a 上面链接的例子中哪个编译器是正确的,g++还是clang++?
- 是否有标准(或建议的)方法来表示 C++ 中的标志?
我能想到几种可能的实现方式:
enum class val { foo, bar, baz, size };
using val_flags = std::set<val>; // (1)
using val_flags = std::vector<bool>; // (2)
using val_flags = std::bitset<val::size>; // (3)
using val_flags = std::underlying_type<val>::type; // (4)
更新:
谢谢大家的回答。我最终恢复了我的旧枚举运算符模板。如果有人感兴趣,可以在这里找到:github.com
【问题讨论】:
-
我认为您在那里可能有未定义的行为(假设
convert是合法的):x不适合val中的任何值,因此由于缺少返回,您会得到未定义的行为声明。 -
我在这里看到的唯一问题是
int convert(val x)有可能不返回任何值。我很确定您的编译器对此发出了警告。