在 switch case 中避免默认值的优雅方法(使用枚举类) [英] Elegant way of avoiding default in switch cases (using enum class)
问题描述
我有一个枚举类,例如:
I have a enum class, for example:
enum class State{
S1,
S2,
S3,
S4
};
每当我进行可能使用此类的 switch/case 语句时,我都希望避免使用默认"语句.不惜一切代价强迫我为所有可能的情况写一份声明.这个想法是,如果我在这个枚举中添加一个新案例S5",由于缺少默认值,编译器将在每次切换时向我发送警告,因为并非所有案例都被涵盖.通过这样做,我最终不会忘记这个新状态可能需要实现特定行为的地方.
And whenever I make a switch/case statement that might use this class, I would like to avoid using a "default" at all costs, to force me to write a statement for all possible cases. The idea is that, if I add a new case in this enum, "S5", due to the lack of a default, the compiler will send me a warning at every switch because not all cases are being covered. By doing so I will not end up forgetting the places where this new state might have a specific behavior to be implemented.
问题是,有各种开关/案例,其中只有一些枚举案例的实现:
The thing is, there are various switch/cases where there is only implementation for some of the enum cases:
switch(state)
{
case S1:
doSomething1();
break;
case S2:
doSomething2();
break;
case S3:
break;
case S4:
break;
}
但我不是很喜欢这些各种各样的空"没有行为的状态的情况,然后是休息.这正是默认"出现的地方.会更优雅,但正如我刚刚解释的那样,这是我想要避免的.
But I'm not very fond of these various "empty" cases for the states that have no behavior, followed by a break. This is exactly where a "default" would be more elegant but as I just explained, that's what I want to avoid.
是否有更优雅(或更高效?)的方式来实现我在这里要做的事情?因为我知道其他编程语言为 switch/case 语句提供了更高级的语法,但我不确定 C++(更具体地说是 C++17)的可能性.
Is there a more elegant (or efficient?) way of achieving what I'm trying to do here? Because I know other programming languages offer more advanced syntax for the switch/case statement, but I'm not sure about the possibilities with C++ (more specifically C++17).
推荐答案
我们也可以使用关联容器来存储处理程序(lambdas 或 functors),然后在找到键后调用处理程序.
We may also use an associate container to store the handlers(lambdas or functors), then call the handlers after finding the key.
添加use断言以确保所有枚举都有相应的处理程序(但这不是编译时错误,我们可以在此处存储函数指针以进行编译时检查,但这会使代码变得丑陋).
Add use assertion to ensure that all enums have the corresponding handlers (But it is not a compile-time error, we can store function pointer here to get a compile-time check but it makes the code ugly).
#include <cassert>
#include <functional>
#include <iostream>
#include <map>
enum class State { S1, S2, S3, S4, Count };
int main(int argc, char* argv[]) {
auto dummy_handler = []() {};
std::map<State, std::function<void()>> mapping = {
{State::S1, []() { std::cout << "s1\n"; }},
{State::S2, []() { std::cout << "s2\n"; }},
{State::S3, dummy_handler },
{State::S4, dummy_handler },
};
assert(mapping.size() == static_cast<size_t>(State::Count)); //May use this
// line to ensume all handlers are set
auto dispatch = [&](State e) {
if (auto itr = mapping.find(e); itr != mapping.end()) {
itr->second();
}
};
auto e = State::S1; // Handlers for s1 will be called
dispatch(e);
e = State::S3;
dispatch(e); // handler for s3
return 0;
}
这篇关于在 switch case 中避免默认值的优雅方法(使用枚举类)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!