c++ - 有效的双向作用域枚举映射

标签 c++ enums c++14

拥有:

enum class A : int {
    FirstA,
    SecondA,
    InvalidB
};

enum class B : int {
    FirstB,
    SecondB,
    InvalidB
};

如何启用这样的功能?

B b = mapper[A::FirstA];
A a = mapper[B::SecondB];

一种可能的解决方案是创建一个 Mapper 模板类,它允许通过构造函数中的初始值设定项列表指定映射,例如:

Mapper<A, B> mapper(
     {
     {A::FirstA,   B::SecondB},
     {A::SecondA,  B::FirstB}
     },
     {A::InvalidA, B::InvalidB} // this is for conversions, where no mapping is specified
);

但在内部,这需要妥协 - 要么是两个映射(从 AB 以及从 BA) >) 或一张 map ,例如从 AB 以及对 BA 转换的线性搜索)。

是否可以在标准 C++14 中实现此功能,因此:

  • 不使用双层容器
  • 两个方向的查找性能同样出色
  • 定义和使用映射相对简单(内部实现不需要)

根据要求,:

  • 它不是身份映射(即 A 中的值未映射到 B 的相同基础值
  • AB 的底层类型可能不同
  • 映射在编译时已知

最佳答案

您可以使用函数模板和完全特化轻松完成此操作。您使主模板返回无效的大小写,然后特化将返回您想要的映射。

如果你有

template<A>
B mapper() { return B::InvalidB; }
template<B>
A mapper() { return A::InvalidA; }

然后您可以添加所有映射值,例如

template<>
B mapper<A::FirstA>() { return B::SecondB; }
template<>
B mapper<A::SecondA>() { return B::FirstB; }
template<>
A mapper<B::FirstB>() { return A::SecondA; }
template<>
A mapper<B::SecondB>() { return A::FirstA; }

然后你会这样调用它

B b = mapper<A::FirstA>();
A a = mapper<B::SecondB>();

这会让你根本没有容器。您甚至可以制作一些宏来使这更容易,例如

#define MAKE_ENUM_MAP(from, to) \
template<from> \
auto mapper() { return to::Invalid; } \
template<to> \
auto mapper() { return from::Invalid; }


#define ADD_MAPPING(from_value, to_value) \
template<> \
auto mapper<from_value>() { return to_value; } \
template<> \
auto mapper<to_value>() { return from_value; }

然后你会像这样使用它们

MAKE_ENUM_MAP(A, B)
ADD_MAPPING(A::FirstA, B::SecondB)
ADD_MAPPING(A::SecondA, B::FirstB)

为您生成所有代码。上述版本使用单个枚举值 Invalid 来表示映射的无效情况。如果您不想这样做,可以向宏添加 fromto 值以用于无效映射,例如

#define MAKE_ENUM_MAP(from, from_value, to, to_value) \
template<from> \
auto mapper() { return to_value; } \
template<to> \
auto mapper() { return from_value; }

你会这样调用它

MAKE_ENUM_MAP(A, A::InvalidA, B, B::InvalidB)

关于c++ - 有效的双向作用域枚举映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55361167/

相关文章:

c++ - 排序谓词不传递对索引对象的引用?

c++ - 在 C++ 中对排列进行排序的最便宜的方法是什么?

c++ - 如何将实际的 sf::Sprite 对象保存在数组或 vector 中? C++

c++ - 在对象声明上下文中获取此类型

java - 从不使用公共(public)嵌套枚举?

ios - 访问快速枚举中的值

c++ - 根据模板参数生成不同大小的初始化列表

c++ - protected 继承是可传递的吗?

html - 如何使用 html 列表格式在 qt 工具提示中缩小缩进?

c# - 字符串的键(枚举)