有没有一种方法可以指定枚举类的值,而不必每次都键入其范围



我有一些函数可以返回成功或一组固定的错误代码。为了识别错误代码,我使用了(类似于(这个老派C风格的枚举声明:

enum {
RESULT_ERROR_BAD_PARAMETER = -3,
RESULT_ERROR_FILE_NOT_FOUND = -2,
RESULT_ERROR_GENERAL = -1,
RESULT_SUCCESS = 0
};
typedef int my_status_t;
my_status_t MyFunc();   // returns a RESULT_* value

这非常有效;调用模式类似于:

if (MyFunc() != RESULT_SUCCESS) printf("Error!n");

然而,它允许my_status_t值隐式转换为int/bool/等,这让人感到不舒服,允许出现这样的粗心错误:

// Compiles but does the wrong thing at run-time -- bad!
if (MyFunc() == false) printf("Error!n");

因此,在我的新代码修订版中,我将其转换为enum class

enum class my_status_t {
RESULT_ERROR_BAD_PARAMETER = -3,
RESULT_ERROR_FILE_NOT_FOUND = -2,
RESULT_ERROR_GENERAL = -1,
RESULT_SUCCESS = 0
};

从编译时检查的角度来看,这非常有效;现在,大多数无意的类型提升都被编译器捕获,迫使程序员返回并以正确的方式执行。

唯一让我困扰的是,新语法很乏味:现在我必须写一些类似的东西:

if (MyFunc() != my_status_t::RESULT_SUCCESS) printf("Error!n");

在每个调用站点——每次都必须键入my_status_t::是乏味的,并且使代码更难阅读,而不会真正增加太多值(因为RESULT_SUCCESS本身就足够独特(

我的问题是,是否有某种using namespace my_status_t;风格的指令可以用来告诉编译器将枚举值从其my_status_t命名空间中导出,这样我就可以引用它们,而不必一直键入my_status_t::前缀?

如果您要键入更多令人讨厌的作用域前缀是enum class中的常量,那么使用它可能是值得的方式:

enum class result {
ERROR_BAD_PARAMETER = -3,
ERROR_FILE_NOT_FOUND = -2,
ERROR_GENERAL = -1,
SUCCESS = 0
};
constexpr result RESULT_ERROR_BAD_PARAMETER = result::ERROR_BAD_PARAMETER;
constexpr result RESULT_FILE_NOT_FOUND = result::ERROR_FILE_NOT_FOUND;
constexpr result RESULT_ERROR_GENERAL = result::ERROR_GENERAL;
constexpr result RESULT_SUCCESS = result::SUCCESS;
result foo() {
return RESULT_SUCCESS;
}
int main()
{
switch (foo())
{
case RESULT_SUCCESS:
;
}
// ^ warning: enumeration value ‘...’ not handled in ...
if (foo() == RESULT_SUCCESS) {
return 0;
}
/* error: no match for ‘operator==’
if (foo() == false) {
return -1;
}
*/
}

(g++-Wall-Wextra-pedantic-std=c++11(

进行此更改:

enum class result {
ERROR_BAD_PARAMETER = -3,
ERROR_FILE_NOT_FOUND = -2,
ERROR_GENERAL = -1,
SUCCESS = 0
};

因为您的枚举值在一个作用域中,所以您不再需要给它们起那么长的名称。

现在您的代码变为:

if (MyFunc() != result::SUCCESS) printf("Error!n");

这比以前长了整整1个字符。

你也可以

using my_status_t = result;

如果您作为类型名称绑定到my_status_t


从C++17开始,没有办法完全避免result::前缀。在C++的后续版本中有关于using ERROR_BAD_PARAMETER = result::ERROR_BAD_PARAMETER;之类的讨论,但我不知道它们是否会进入C++20。

这里有一种方法:

enum class my_status_t { };
inline constexpr my_status_t RESULT_ERROR_BAD_PARAMETER = my_status_t(-3);
// add other enum values here

不幸的是,这样您就失去了enum的一些好特性。如果您没有处理开关中的值,类似编译器可以警告您(如果您有大值,请不要忘记设置enum class的底层类型(。

所以我实际上不推荐这种方式(我更喜欢亚克的解决方案(,但也许这个答案无论如何都能帮助你。。。

最新更新