vitamin_caig (vitamin_caig) wrote,
vitamin_caig
vitamin_caig

работа с enum

Довольно часто возникает нужда конвертировать перечисления в строковые эквиваленты и обратно. Возникла такая проблема и у меня.



  //types definitions
  typedef ... String;

  //some common tools
  template<class T, std::size_t D>
  inline const T* ArrayEnd(const T (&arr)[D])
  {
    return arr + D;
  }

  //common value-list initializable struct
  template<class T>
  struct EnumStruct
  {
    const T AsValue;
    const String AsString;

    bool operator == (T val) const
    {
      return AsValue == val;
    }

    bool operator == (const String& str) const
    {
      return AsString == str;
    }
  };

  //value-type-specific trait
  template<class T>
  struct EnumTrait
  {
    static const EnumStruct<T> Map[];
    static const EnumStruct<T> DefaultValue;
  };

  //common code
  template<class T>
  inline String EnumToString(T val)
  {
    const EnumStruct<T>* it = std::find(EnumTrait<T>::Map, ArrayEnd(EnumTrait<T>::Map), val);
    return (it == ArrayEnd(EnumTrait<T>::Map)) ? EnumTrait<T>::DefaultValue.AsString : it->AsString;
  }

  template<class T>
  inline T EnumFromString(const String& str)
  {
    const EnumStruct<T>* it = std::find(EnumTrait<T>::Map, ArrayEnd(EnumTrait<T>::Map), str);
    return (it == ArrayEnd(EnumTrait<T>::Map)) ? EnumTrait<T>::DefaultValue.AsValue : it->AsValue;
  }


Смысл простой, как две копейки- объявляем карту соответствия и дефолтные заглушки. Потом вызываем соответствующие функции.

Как пользоваться (в лучших традициях индусского кода:) ):
  enum MyBool
  {
    FALSE,
    TRUE,
    MAYBE,
  };
  const String::value_type VALUE_FALSE[] = {'f', 'a', 'l', 's', 'e', '\0'};
  const String::value_type VALUE_TRUE[] = {'t', 'r', 'u', 'e', '\0'};
  const String::value_type VALUE_MAYBE[] = {'m', 'a', 'y', 'b', 'e', '\0'};
  template<>const EnumStruct<MyBool> EnumTrait<MyBool>::Map[] =
  {
    {FALSE, VALUE_FALSE},
    {TRUE, VALUE_TRUE},
    {MAYBE, VALUE_MAYBE}
  };
  template<>const EnumStruct<MyBool> EnumTrait<MyBool>::DefaultValue =
  {
    MAYBE, VALUE_MAYBE
  };

  ...
  assert(EnumToString(FALSE) == VALUE_FALSE);
  assert(EnumToString(static_cast<MyBool>(100)) == VALUE_MAYBE);//fallback
  assert(EnumFromString<MyBool>(VALUE_TRUE) == TRUE);
  const String::value_type abrakadabra[] = {'a', 'b', 'r', 'a', 'k', 'a', 'd', 'a', 'b', 'r', 'a', '\0'}
  assert(EnumFromString<MyBool>(abrakadabra) == MAYBE);//fallback


Код был надерган из разных исходников, так что без обработки напильником может и не собраться сразу:)
Tags: c++, программирование
Subscribe

  • Android

    Неожиданно обнаружил, что больше года не писал сюда. Как-то не тянуло:) Кому не интересны всякие там технические детали, могут не читать. В…

  • немного о проектировании интерфейсов

    Давно уже ничего не писал, а тут зуд в известном месте заставляет немного размять мозги и занять их тем, для чего они (мои мозги) предназначены-…

  • PR for software

    Ох, нелегкая это работа продвигать свой софт в массы. Даже если этот софт бесплатный и единственное, что требуется от пользователя- сообщать о багах…

  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 4 comments