switch() 中未处理的枚举 class 值 - 异常还是断言?
Unhandled enum class value in switch() - Exception or Assert?
lvl
是一个 enum class
.
switch(lvl)
{
case LogLevel::Trace:
return "Trace";
case LogLevel::Debug:
return "Debug";
case LogLevel::Info:
return "Info";
case LogLevel::Warning:
return "Warning";
case LogLevel::Error:
return "Error";
case LogLevel::Fatal:
return "Fatal";
default:
assert(0 && "Unhandled LogLevel in LevelToStr"); return "???"; // This one?
throw std::invalid_argument( "Unhandled LogLevel in LevelToStr" ); // or this one?
}
共识是 default
应该存在,但 related question 中的意见对其应该做什么存在分歧。让整个事情崩溃?崩溃当前线程?尝试优雅地处理异常?
双方在评论中提出了一些论点,但讨论还不是很确定。
有人可以给出一个全面的答案,应该使用哪个,或者在什么条件下使用?
这完全取决于您的系统要求。
我实际上认为在这种情况下最好不要使用 default:
。如果您将其遗漏,那么如果您在编译时遗漏了一个案例,您将收到一个有用的警告。如果您使用 -Werror 进行编译,那么您的程序将无法编译,直到您修复了警告。
void handle_something(LogLevel lvl)
{
switch(lvl)
{
case LogLevel::Trace:
return "Trace";
case LogLevel::Debug:
return "Debug";
case LogLevel::Info:
return "Info";
case LogLevel::Warning:
return "Warning";
case LogLevel::Error:
return "Error";
case LogLevel::Fatal:
return "Fatal";
// note: no default case - better not to suppress the warning
}
// handle the default case here
// ok, so now we have a warning at compilation time if we miss one (good!)
// next question: can the program possibly continue if this value is wrong?
// if yes...
return some_default_action();
// ... do we want debug builds to stop here? Often yes since
// ... this condition is symptomatic of a more serious problem
// ... somewhere else
std::assert(!"invalid log level");
// ...if no, do we want to provide information as to why
// ... which can be nested into an exception chain and presented
// ... to someone for diagnosis?
throw std::logic_error("invalid error level: " + std::to_string(static_cast<int>(lvl));
// ... or are we in some mission-critical system which must abort and
// ... restart the application when it encounters a logic error?
store_error_in_syslog(fatal, "invalid log level");
std::abort();
}
lvl
是一个 enum class
.
switch(lvl)
{
case LogLevel::Trace:
return "Trace";
case LogLevel::Debug:
return "Debug";
case LogLevel::Info:
return "Info";
case LogLevel::Warning:
return "Warning";
case LogLevel::Error:
return "Error";
case LogLevel::Fatal:
return "Fatal";
default:
assert(0 && "Unhandled LogLevel in LevelToStr"); return "???"; // This one?
throw std::invalid_argument( "Unhandled LogLevel in LevelToStr" ); // or this one?
}
共识是 default
应该存在,但 related question 中的意见对其应该做什么存在分歧。让整个事情崩溃?崩溃当前线程?尝试优雅地处理异常?
双方在评论中提出了一些论点,但讨论还不是很确定。
有人可以给出一个全面的答案,应该使用哪个,或者在什么条件下使用?
这完全取决于您的系统要求。
我实际上认为在这种情况下最好不要使用 default:
。如果您将其遗漏,那么如果您在编译时遗漏了一个案例,您将收到一个有用的警告。如果您使用 -Werror 进行编译,那么您的程序将无法编译,直到您修复了警告。
void handle_something(LogLevel lvl)
{
switch(lvl)
{
case LogLevel::Trace:
return "Trace";
case LogLevel::Debug:
return "Debug";
case LogLevel::Info:
return "Info";
case LogLevel::Warning:
return "Warning";
case LogLevel::Error:
return "Error";
case LogLevel::Fatal:
return "Fatal";
// note: no default case - better not to suppress the warning
}
// handle the default case here
// ok, so now we have a warning at compilation time if we miss one (good!)
// next question: can the program possibly continue if this value is wrong?
// if yes...
return some_default_action();
// ... do we want debug builds to stop here? Often yes since
// ... this condition is symptomatic of a more serious problem
// ... somewhere else
std::assert(!"invalid log level");
// ...if no, do we want to provide information as to why
// ... which can be nested into an exception chain and presented
// ... to someone for diagnosis?
throw std::logic_error("invalid error level: " + std::to_string(static_cast<int>(lvl));
// ... or are we in some mission-critical system which must abort and
// ... restart the application when it encounters a logic error?
store_error_in_syslog(fatal, "invalid log level");
std::abort();
}