我有一些函数可以返回成功或一组固定的错误代码。为了识别错误代码,我使用了(类似于(这个老派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
的底层类型(。
所以我实际上不推荐这种方式(我更喜欢亚克的解决方案(,但也许这个答案无论如何都能帮助你。。。