通用 int -> 可以使用模板进行枚举转换吗?

generic int -> enum conversion with templates possible?

本文关键字:枚举 转换 int gt 可以使 通用      更新时间:2023-10-16

我使用这样的函数将int(从遗留 API)转换为enum

TestEnum to_test_enum(int value) {
    TestEnum converted(static_cast<TestEnum>(value));
#   pragma GCC diagnostic push
#   pragma GCC diagnostic error "-Wswitch"
    switch (converted) {
        case TestEnum::A:
        case TestEnum::B:
            return converted;
    }
#   pragma GCC diagnostic pop
    throw std::runtime_error("wrong value");
}

如果将无效值传递给to_enumto_test_enum会抛出异常,否则返回相应的TestEnum值。pragma确保在缺少合法值的情况下,我会收到编译器错误。

像这样的行现在将转换一个整数并在运行时进行有效性检查:

enum class TestEnum {
    A = 1,
    B = 2,
};
auto v1 = to_test_enum(2);
auto v2 = to_test_enum(3);  // will throw

问题:我想知道是否有可能使用某种模板魔术将其转换为函数模板:

template<class E>
E to_enum(int value) {
    E converted(static_cast<E>(value));
    switch (converted) {
        EACH ELEMENT e IN E: case e:   <--- here goes some unrolling magic
            return converted;
    }
    throw std::runtime_error("wrong value");
}

然后,该函数将像这样使用:

auto v1 = to_enum<TestEnum>(2);
auto v2 = to_enum<TestEnum>(3);  // will throw

我不确定我是否理解你想做什么。请参阅下面的一个想法。您必须定义自己的map_enum< your_enum >()才能将整数映射到枚举。

#include <map>
#include <iostream>
template< typename E > const std::map< int, E >& map_enum()
{
  return 0;
}
template < typename E > E to_enum( int ai )
{
  auto m = map_enum< E >();
  auto const i = m.find( ai );
  return i == m.end() ? throw -1 : i->second;
}
// { old api
#define RED 0
#define GREEN 1
#define BLUE 2
int old_api_fun()
{
  return 2;
}
// } old api
// { your code
enum color_e
{
  red = RED,
  green = GREEN,
  blue = BLUE
};
template<> const std::map< int, color_e >& map_enum()
{
  static std::map< int, color_e > m ={ { RED, red }, { GREEN, green }, { BLUE, blue } };
  return m;
}
// } your code
int main()
{
  try
  {
    auto r = to_enum< color_e >( old_api_fun() );
    std::cout << "success";
  }
  catch ( int )
  {
    std::cout << "failed";
  }
  return 0;
}