3 回答
TA贡献1770条经验 获得超3个赞
一个不错的折衷方法是这样的:
struct Flintstones {
enum E {
Fred,
Barney,
Wilma
};
};
Flintstones::E fred = Flintstones::Fred;
Flintstones::E barney = Flintstones::Barney;
从版本上来说,它不是类型安全的,但是用法比标准枚举更好,并且在需要时仍可以利用整数转换。
TA贡献1784条经验 获得超9个赞
我个人使用的是typesafe枚举用法的改编版本。它没有提供您在编辑中陈述的所有五个“要求”,但无论如何我还是非常不同意其中的一些。例如,我看不到Prio#4(将值转换为字符串)与类型安全有何关系。无论如何,大多数时间字符串表示形式的单个值都应与类型的定义分开(考虑一下i18n的简单原因)。Prio#5(迭代,它是可选的)是我想看到的枚举中自然发生的最好的事情之一,因此令您感到遗憾的是,它在您的请求中显示为“可选”,但似乎可以通过以下方式更好地解决一个单独的迭代系统,例如begin/end 函数或enum_iterator,这使它们可与STL和C ++ 11 foreach无缝协作。
OTOH这个简单的成语很好地提供了Prio#3 Prio#1,这是因为它实际上只会包装enum带有更多类型信息的。更不用说这是一个非常简单的解决方案,在很大程度上不需要任何外部依赖标头,因此很容易携带。它还具有使枚举范围为a-la-C ++ 11的优点:
// This doesn't compile, and if it did it wouldn't work anyway
enum colors { salmon, .... };
enum fishes { salmon, .... };
// This, however, works seamlessly.
struct colors_def { enum type { salmon, .... }; };
struct fishes_def { enum type { salmon, .... }; };
typedef typesafe_enum<colors_def> colors;
typedef typesafe_enum<fishes_def> fishes;
解决方案提供的唯一“漏洞”是,它无法解决无法阻止enum将不同类型的s(或an enum和int)直接进行比较的事实,因为直接使用值时会强制执行隐式转换至int:
if (colors::salmon == fishes::salmon) { .../* Ooops! */... }
但是到目前为止,我发现可以通过简单地与编译器进行更好的比较来解决这些问题,例如,显式提供一个可以比较任意两种不同enum类型的运算符,然后强制其失败:
// I'm using backports of C++11 utilities like static_assert and enable_if
template <typename Enum1, typename Enum2>
typename enable_if< (is_enum<Enum1>::value && is_enum<Enum2>::value) && (false == is_same<Enum1,Enum2>::value) , bool >
::type operator== (Enum1, Enum2) {
static_assert (false, "Comparing enumerations of different types!");
}
尽管到目前为止似乎还没有破坏代码,并且确实可以不处理其他问题而明确地处理特定问题,但是我不确定这是“ 应该 ”做的事情(我怀疑它会干扰enum已参与其他地方声明的转换运算符;我很乐意收到对此的评论)。
将此与上面的类型安全习惯相结合,就可以enum class在操作性(可读性和可维护性)方面相对接近C ++ 11 ,而不必做任何过于晦涩的事情。而且我不得不承认这样做很有趣,我从没想过要问编译器是否在处理enums ...
- 3 回答
- 0 关注
- 632 浏览
添加回答
举报