2016-05-09 11 views
-1

lvl ist ein enum class.Nicht behandelter Enum-Klassenwert in switch() - Exception oder Assert?

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? 
} 

Der Konsens ist die default sollte es sein, aber die Meinungen in der related question sind geteilt, was sollte es tun. Crash das Ganze? Den aktuellen Thread abstürzen? Versuchen Sie, die Ausnahme ordnungsgemäß zu behandeln?

Die Seiten präsentieren einige Argumente in den Kommentaren, aber die Diskussion ist nicht ganz schlüssig.

Könnte jemand eine umfassende Antwort geben, welche verwendet werden sollte oder unter welchen Bedingungen?

+0

Also, Schluss mit den Stimmen und Schlussabstimmung: Niemand wirklich weiß. –

+0

_ "Also, mit den Stimmen schließen und Stimmen schließen ..." _ Nein, Ihre Schlussfolgerung ist falsch. Es ist Ihre Frage, die an erster Stelle _too breit_, _in erster Linie meinungsbezogen_ ist. –

+0

@ πάνταῥεῖ: Genau zwei Optionen. Kannst du wirklich ein Buch schreiben, auf das du je nach deiner Situation auswählst? Und ist es nur eine Frage des persönlichen Geschmacks und niemand kann ein zwingendes logisches Argument präsentieren, wo welches besser ist? –

Antwort

2

Es hängt vollständig von den Anforderungen Ihres Systems ab.

Ich würde tatsächlich argumentieren, dass es besser ist, default: in diesem Fall nicht zu verwenden. Wenn Sie es auslassen, erhalten Sie eine nützliche Warnung, wenn Sie einen Fall zum Zeitpunkt der Kompilierung verpasst haben. Wenn Sie mit -Werror kompilieren, wird Ihr Programm nicht kompiliert, bis Sie die Warnung behoben haben.

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(); 
}