C++ 中的枚举映射

Posted

技术标签:

【中文标题】C++ 中的枚举映射【英文标题】:Enum mapping in C++ 【发布时间】:2016-09-22 09:30:08 【问题描述】:

我需要在两组枚举之间进行映射。枚举之间是一一对应的。

例如

第一组:

Enum1A, B, C, D;
Enumx...
Enumy...

第二套:

Enum2A2, B2, C2, D2;
Enumx2...
Enumy2...

地图功能:

Enum1 map(Enum2);
Enumx map(Enumx2);
Enumy map(Enumy2);

我正在寻找一种优雅的方式来制作这张地图。 我可以使用模板专业化吗?还是枚举都被视为整数?

例子:

class MapHelper
public:
    template<typename From, To>
    static To map(From from);

    template<>
    static Enum1 map<Enum2, Enum1>(Enum2 from)
    return static_cast<Enum1>(from);
    
;

【问题讨论】:

你走了多远?你试过什么?您遇到的具体问题是什么? :) 我遇到的问题是我还必须指定返回类型并用两种类型参数化函数,我想只用一种参数化它并在后面有一个类型映射,但我没有不知道怎么做。 拜托,你能告诉我们你的部分解决方案吗?这样我们就可以确定我们谈论的是同一件事并为正确的问题提供帮助:) 我加了一个例子 枚举是否总是按顺序排列,并且每个枚举中的元素数量相同? 【参考方案1】:

你可以使用特质:

template<Enum1 V> struct ToEnum2;
template<> struct ToEnum2<Enum1::A>  static constexpr Enum2 value = Enum2::A; ;
template<> struct ToEnum2<Enum1::B>  static constexpr Enum2 value = Enum2::B; ;
// ...

然后,只要你有一个来自Enum1 的值,你就可以找到来自Enum2 的值:

Enum1<VALUE>::value;

它遵循一个最小的工作示例:

enum class Enum1  A, B ;
enum class Enum2  C, D ;

template<Enum1 E> struct Map;
template<> struct Map<Enum1::A>  static constexpr Enum2 value = Enum2::C; ;
template<> struct Map<Enum1::B>  static constexpr Enum2 value = Enum2::D; ;

int main() 
    static_assert(Map<Enum1::A>::value == Enum2::C, "!");
    static_assert(Map<Enum1::B>::value == Enum2::D, "!");

【讨论】:

那太好了! @yonutix Traits 在 C++ 中很常见。希望这个答案可以帮助您解决真正的问题。【参考方案2】:

假设您的 enum 具有相同的值,您可以这样做:

template <typename E> struct MappingEnum;

template <typename E>
using MappingEnum_t = typename MappingEnum<E>::type;

template <> struct MappingEnum<Enum1>

    using type = Enum2;
;

然后

template <typename E>
MappingEnum_t<T> map(E e)  return static_cast<MappingEnum_t<T>>(e); 

【讨论】:

我会说相同的值和直接映射,第一个枚举来自第一个枚举,第一个来自第二个枚举,依此类推。人们实际上可以争论拥有这两个枚举的效用......嗯......【参考方案3】:

C++11 解决方案:

#include <type_traits>

template<typename From, typename To>
To map(From e) 
    return static_cast<To>(
        static_cast<typename std::underlying_type<To>::type>(
        static_cast<typename std::underlying_type<From>::type>(e)));

这种转换级联非常明确并且支持枚举类。

对于较旧的 C++ 版本和没有 class 的枚举,static_cast&lt;Enum2&gt;(e) 就足够了。

编辑:

通过模板特化,您可以使用map 而无需明确指定任何类型:

enum class Enum1: int A, B, C, D;
enum class Enum2: char A1, B1, C1, D1;

template<typename T>
struct target_enum 
;

template<>
struct target_enum<Enum1> 
    typedef Enum2 type;
;

template<typename From>
typename target_enum<From>::type map(From e) 
    typedef typename target_enum<From>::type To;
    return static_cast<To>(
        static_cast<typename std::underlying_type<To>::type>(
        static_cast<typename std::underlying_type<From>::type>(e)));

然后您可以致电map(Enum1::A)。也适用于简单的非类枚举。

【讨论】:

是的,但我必须始终指定 map,我只想将 map 和 To 输入到 hashmap[From] = To 这样的哈希图中。 【参考方案4】:

除了您现在添加到问题中的静态转换之外,您还可以通过使用前一个枚举中的值设置等效枚举中的值来使映射更容易/更明确:-

enum Enum1

    a = 1,
    b = 2,
;

enum Enum2

    z = a,
    y = b
;

还有一种将模板折叠成只需要指定目标的方法...

template <typename targettype>
class Converter

    public:
    template<typename sourceType>
    static targettype Convert(sourceType from)
    
        return static_cast<targettype>(from);
    
;

可调用为:-

Converter<Enum2>::Convert(someEnum1);

【讨论】:

由于项目限制,这不是一个选项 什么样的限制可以防止这种情况发生? Enum1 和 Enum2 位于不同的文件中,在 Enum2 中我无法访问 Enum1 以访问 Enum1::a。 OK,尽管如果您可以将 enum1 的定义包含在定义 enum2 的文件中,单独的文件仍然可以。如果不是,那么就足够公平了,但如果你可以包含它,它就不必为每个值单独定义映射。

以上是关于C++ 中的枚举映射的主要内容,如果未能解决你的问题,请参考以下文章

使用固定值映射 JPA 中的枚举?

如何使用 AutoMapper 将 json 请求 dto 中的 OData 枚举字符串映射到实体枚举属性

NHibernate 中的映射表枚举

如何映射枚举以选择 Storybook 中的下拉列表?

C++ 中的全局枚举

C++中的enum枚举