简体   繁体   English

来自 int 的强类型枚举。 C++11

[英]strongly typed enum from int . C++11

We are recently converting all enum to class enum.我们最近将所有枚举转换为 class 枚举。

enum class Launches : std::uint32_t {
  D_FROM_FILE=0,
  D_FROM_FDISK,
  D_FROM_RDDISK,
  D_FROM_USB,
  D_FROM_UI,
  D_FROM_NET,
  D_FROM_DEFAULT
};

Launches  launches ;

I need to assign launches values based on int that i received from command line我需要根据从命令行收到的 int 分配launches

This is what I am doing after conversion to strongly typed enum这就是我在转换为强类型枚举后所做的事情

if (receivedInt  == 1)
   launches = D_FROM_FDISK;

I want to avoid and do like我想避免并喜欢

launches = receivedInt;

We fail to compile as this is what strongly typed int are supposed to do.我们无法编译,因为这是强类型int应该做的。

I want to avoid if and switch cases on receivedInt .我想避免ifswitch case on receivedInt

launches = (Launches)receivedInt ; // this compiles ..

but I am hesitant on this or on using static_cast ... whats the proper way?但我对此或使用static_cast犹豫不决......正确的方法是什么?

using static_cast etc?使用static_cast等? What benefit will remain on using strongly types enums then那么使用强类型枚举会有什么好处呢?

If you don't want to do typecasts you can use an unordered_map.如果您不想进行类型转换,您可以使用 unordered_map。 Here is an example that converts an int you could get from commandline into an enum value in a typesafe manner这是一个示例,它将您可以从命令行获取的 int 以类型安全的方式转换为枚举值

#include <cassert>
#include <string>
#include <unordered_map>

enum class Launches 
{
    D_FROM_FILE = 0,
    D_FROM_FDISK,
    D_FROM_RDDISK,
    D_FROM_USB,
    D_FROM_UI,
    D_FROM_NET,
    D_FROM_DEFAULT
};

Launches get_option(const int option)
{
    static const std::unordered_map<int, Launches> launch_options
    {
        {1, Launches::D_FROM_FILE},
        {2, Launches::D_FROM_FDISK},
        //.. etc..
        {6, Launches::D_FROM_NET}
    };

    auto it = launch_options.find(option);
    if (it != launch_options.end())
    {
        return it->second;
    }

    return Launches::D_FROM_DEFAULT;
}


int main()
{
    auto option = get_option(1);
    assert(option == Launches::D_FROM_FILE);

    return 0;
}

What you can do, - create a simple conversion function, check rages and then do the trivial type casting.你可以做什么, - 创建一个简单的转换 function,检查 rages 然后进行简单的类型转换。

#include <system_error>
...
Launches from_code(std::error_code& ec,int code) noexcept 
{
  Launches ret = Launches::D_FROM_DEFAULT;
  if( code < 0 || code > 7) {
    ec = std::make_error_code(std::errc::invalid_argument);
  } else {
    ret = static_cast<Launches>( static_cast<uint32_t>(code) );
  }
  return ret;
}

std::error_code ec;
Lanches launches = from_code(ec,code);
if(ec) {
  // handle error, this code simply thows you can insert your safe logic
  throw std::system_error(ec); 
}
// do what ever you need to
switch(launches) {
  case Launches::D_FROM_FILE:
  ...
  break;
  ...
}

Stroustrup - The enum classes address three problems with conventional c++ enumerations: Stroustrup - enum类解决了传统 c++ 枚举的三个问题:

  • conventional enums implicitly convert to int ;常规枚举隐式转换为 int
  • conventional enums export their values to the surrounding scope ;常规枚举将其值导出到周围的 scope
  • the underlying type of conventional enum cannot be specified.无法指定常规枚举的基础类型

If you use enum s for IO, you will have to convert them at some point.如果您将enum用于 IO,您将不得不在某个时候转换它们。 Your enum is defined as a continuous range .您的enum被定义为一个连续的范围 You could add a First and a Last value and check the range ( demo ):您可以添加FirstLast值并检查范围( demo ):

#include <iostream>
#include <exception>

enum class Launches : std::uint32_t
{
  First = 0,

  D_FROM_FILE = First,
  D_FROM_FDISK,
  D_FROM_RDDISK,
  D_FROM_USB,
  D_FROM_UI,
  D_FROM_NET,
  D_FROM_DEFAULT,

  Last = D_FROM_DEFAULT
};

template< typename E, typename T >
Launches seq_enum_cast(T  v)
{
  return v >= static_cast<T>(E::First) && v <= static_cast<T>(E::Last)
    ? static_cast<E>(v)
    : throw std::bad_cast();
}

int main()
{
  try
  {
    auto a = seq_enum_cast<Launches>(1);
    std::cout << "a - success\n";
    auto b = seq_enum_cast<Launches>(-3); // fails
    std::cout << "b - success\n";
  }
  catch (const std::bad_cast& e)
  {
    std::cout << e.what();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM