在 switch case 中避免默认值的优雅方法(使用枚举类) [英] Elegant way of avoiding default in switch cases (using enum class)

查看:97
本文介绍了在 switch case 中避免默认值的优雅方法(使用枚举类)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举类,例如:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆