2016-09-22 2 views
1

Мне нужно сделать сопоставление между двумя наборами перечислений. Соответствие между перечислениями один к одному.Отображение перечисления в C++

Например

Первый набор:

Enum1{A, B, C, D}; 
Enumx... 
Enumy... 

Второй набор:

Enum2{A2, 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); 
    } 
}; 
+0

Как далеко вы пришли? Что вы пробовали? Каковы конкретные проблемы, которые у вас были? :) –

+0

Проблема, с которой я столкнулся, заключалась в том, что я должен указать также тип возвращаемого значения и параметризовать функцию с двумя типами, я хотел бы параметризовать ее только с одним и иметь карту типов позади, но я не знаю, как это сделать Это. – yonutix

+0

Пожалуйста, вы можете показать нам свое частичное решение? Таким образом, мы можем быть уверены, что мы говорим об одном и том же и предлагаем помощь с правильными проблемами :) –

ответ

0

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<Enum2>(e) было бы достаточно.

Edit:

С специализации шаблона вы можете использовать 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). Также работает с простыми, неклассовыми перечислениями.

+0

Да, но мне нужно всегда указывать карту , я бы хотел сделать только карту и напечатать, чтобы быть каким-то образом в хэшмапе вроде hashmap [From ] = To. – yonutix

0

В дополнении к статической отливке, которые вы добавили на свой вопрос, вы можете сделать отображение проще/более четко устанавливая значения в эквивалентных перечислениях, используя значения из предыдущего перечисления: -

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); 
+0

Это не вариант из-за ограничений проекта – yonutix

+0

Какие ограничения могут помешать этому? – ROX

+0

Enum1 и Enum2 находятся в отдельных файлах, в Enum2 У меня нет доступа к Enum1 для доступа к Enum1 :: a. – yonutix

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, "!"); 
} 
+0

Это очень приятно! – yonutix

+0

@yonutix Черты довольно распространены в C++. Надеясь, что этот ответ поможет вам в решении вашей реальной проблемы. – skypjack

1

Предполагая, что ваши 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); } 
+0

Я бы сказал, что те же vaues и direct mapping, первый из первого перечисления с первым из второго перечисления и так далее. На самом деле можно было бы спорить об использовании этих двух перечислений ... Ух ... – skypjack

Смежные вопросы