Необработанное значение класса перечисления в switch () - исключение или утверждение?

lvl is an 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 должно быть, но мнения в связанный вопрос разделены на то, что он должен делать. Разбить все это? Разбить текущую ветку? Пытаться аккуратно обработать исключение?

В комментариях стороны приводят некоторые аргументы, но обсуждение не совсем однозначное.

Может ли кто-нибудь дать исчерпывающий ответ, какой из них следует использовать или в каких условиях?


person SF.    schedule 09.05.2016    source источник
comment
Итак, подводя итоги голосованием и закрытым голосованием: на самом деле никто не знает.   -  person SF.    schedule 09.05.2016
comment
Итак, завершение голосованием и закрытым голосованием ... Нет, ваш вывод неверен. Это ваш вопрос, который слишком широк, в первую очередь основан на мнении.   -  person πάντα ῥεῖ    schedule 09.05.2016
comment
@ πάνταῥεῖ: Точно два варианта. Вы действительно можете написать книгу, из которой выбрать в зависимости от вашей ситуации? И это просто вопрос личных вкусов, и никто не может представить убедительный логический аргумент, где какой из них лучше?   -  person SF.    schedule 09.05.2016
comment
@SF. Can you really write a book on which one to choose depending on your situation? Вы хотите сказать, что нет целых книг, посвященных исключениям? Я был бы удивлен, если бы это было так.   -  person uh oh somebody needs a pupper    schedule 09.05.2016
comment
@ user6292850: Исключения легко могут охватить всю книгу. Наследование и структурирование, шаблоны проектирования, основанные на исключениях, постепенное восстановление после исключения, внутренние механизмы развертывания стека и т. Д. Это здесь, однако, двоичный выбор. Ближайший предмет, который является достаточно широким двоичным выбором, чтобы вы могли написать по нему книгу, - это ли Бог существует ?.   -  person SF.    schedule 09.05.2016
comment
@SF Ну, как правильно сказал @Richard: Это полностью зависит от требований вашей системы.   -  person πάντα ῥεῖ    schedule 09.05.2016
comment
@ πάνταῥεῖ: Да, это так. Но КАК это зависит? Какие факторы следует учитывать при выборе? В настоящее время StackOverflow занимается только указанием на опечатки в программах студентов, а вопросы о том, как научиться принимать осмысленные решения при разработке программ, стали не по теме? Каждый из двух вариантов имеет ряд преимуществ и недостатков. Учитывая их соответствие требованиям проекта, я могу сделать выбор. Но у меня недостаточно хорошего представления о достоинствах и недостатках каждого из них.   -  person SF.    schedule 09.05.2016
comment
@SF Не уверен, но, возможно, ваш вопрос больше подходит для Programmers SE.   -  person πάντα ῥεῖ    schedule 09.05.2016
comment
@ πάνταῥεῖ: С этим я согласен.   -  person SF.    schedule 09.05.2016


Ответы (1)


Это полностью зависит от требований вашей системы.

На самом деле я бы сказал, что в этом случае лучше не использовать 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();
}
person Richard Hodges    schedule 09.05.2016