安全使用严格枚举 C++ 11

safe use strict enum c++ 11

本文关键字:枚举 C++ 安全      更新时间:2023-10-16

如何在 c++ 11 中安全使用枚举?下面的代码,我正在尝试强制工作...

我需要安全的方法以适当的方式与严格枚举相互转换。

#include <iostream>
class test{
enum class fruits:int{
apple,
banana,
pear
}m_fruits{fruits::apple};
fruits operator=(int _i){
switch(_i){
case 0:
return fruits::apple;
case 1:
return fruits::banana;
case 2:
return fruits::pear;
default:
return fruits::apple;
}
}
int operator=(fruits _f){
return static_cast<int>(_f);
}

public:
void function_worked(){
fruits f = operator=(155);
std::cout << operator=(f);
}
void function_wanted(){
fruits f = 155;
std::cout << f;
}
};

unscoped enum

无作用域枚举的两个缺点是

它们污染了命名空间

{} 中的标识符泄漏到周围的范围内,这可能会让不知情的开发人员措手不及。更糟糕的是,开发人员的大脑倾向于为枚举器列表选择标识符,这些标识符在其他上下文中也可能有用。

enum Direction { x, y, z };
// ...
auto x = 42;  // Error!

他们允许荒谬的语义悲剧

因为隐式转换为基础类型。

enum Direction { x, y, z };
Direction axis = x;
if (axis < 12.5)
std::cout sqrt(axis);

作用域枚举

解决了这两个问题,枚举器列表标识符不会泄漏到周围的范围内,并且没有隐式转换。

第一步,这是您决定使用作用域枚举时得到的。

宗教或工具

虽然一般来说,正确的设计应该顺利地与那些作用域枚举一起工作,但对老式语义悲剧的需求可能是错误设计决策的标志。我看不出有什么理由不利用作用域枚举的非作用域污染属性并故意放弃类型安全。

非类型安全+非范围污染仍优于非类型安全+范围污染

很难说为什么在问题的代码中需要

fruits f = 155;

什么时候你可以简单地写

fruits f = fruits::apple;

虽然两者都包含一定数量的魔法,但第一个要神秘得多,因为该枚举的明显逻辑并不表明 155 是一个苹果。

幸运的是,第一个表达式无法正常工作。

另一方面,如果它必须真的是一个 int 赋值,那么你只需要付出代价:

fruits f = static_cast<fruits>(155);

另一方面

std::cout << static_cast<int>(f);

对我来说似乎绝对没问题,例如用于调试或序列化或其他什么。

void function_wanted(){
fruits f = fruits::apple;
std::cout << static_cast<int>(f);
}

对我来说似乎是一个很好的解决方案。

备注

示例

fruits f = fruits::apple;

恕我直言,为什么枚举器名称在大多数情况下应该是单数的,尽管枚举定义包括大量标识符。