Есть ли библиотека C ++ для создания сильных перечислений?

В идеале мне бы хотелось, чтобы следующие примеры работали, но я полагаю, что некоторые из них не могут быть реализованы на C ++.

{
  typedef StrongEnum<Red=0, Green=1, Blue=2> Color; // not a C++ syntax
  Color c = Color::Red;  // static const 
  Color d;  //error: default constructor is private 
  Color d = c;
  Color e = Color::OfInt(5); // ifdef DEBUG - Runtime error: Enum out of range 

  int sum = 0;

  // I do have these macros, but separate for each enum - FOREACH_COLOR(c)
  FOREACH_ENUM (Color c) { 
    sum += c.ToInt ();
  }

  ArrayMap<Color, string> map;  // Internally this is const size array, possible
  map [Color::Red] = "red";     // because Color have static const Limit = 3 inisde. 

  // Advanced: EnumPair does bitpacking.
  // currently I implement it manually for every pair of Enum's I need.
  typedef EnumPair <door=Color, window=Color> ColorPair; // I guess I can't get this, can I?
  ColorPair pair (door = Color::Red, window = Color::Green); // I guess I can't give the labels here or one line above, can I?
  Color w = pair.window;
  Color w = pair.window ();
}

Я их часто использую и в настоящее время пишу каждую с нуля. Я знаю, что полное универсальное решение - это мечта, поэтому я приветствую любые частичные решения. Может, кто-нибудь создал библиотеку или генератор кода?

Обновление 1:

This и эти вопросы связаны. Я изучаю, какие проблемы можно решить с их помощью.


person Łukasz Lew    schedule 27.10.2009    source источник
comment
Но частичное не означает реализацию класса Color выше. Это означает частичное универсальное Enum, чтобы избежать повторной реализации одних и тех же методов снова и снова.   -  person Łukasz Lew    schedule 27.10.2009
comment
Вы ищете безопасные этикетки? artima.com/cppsource/safelabels.html   -  person Dominic Rodger    schedule 27.10.2009
comment
И да, я знаю о классе enum в C ++ 0x, но он сам по себе не решает мою проблему.   -  person Łukasz Lew    schedule 27.10.2009


Ответы (2)


Вот что я понял:

#include <cstdio>
#include <string>
#include <map>

namespace Color
{
    typedef enum
    {
        Red = 0,
        Green = 1,
        Blue = 2
    } Color;

    Color colors[] = {Red, Green, Blue}; // same order as above,
                                         //to preserve index.

    //int colors_len = sizeof(colors)/sizeof(Color);
    // (if you want to check for valid values)

    static inline Color OfInt(int value)
    {
        // if(value >= colors_len) do error thing;
        return colors[value];
    }
}

int main()
{
    Color::Color c = Color::Red;

    printf("%d,", c);

    c = Color::OfInt(1);

    printf("%d,", c);

    c = Color::Blue;

    printf("%d\n", c);

    std::map<Color::Color, std::string> map;

    map[Color::Red] = "red";

    return 0;
}

По крайней мере, он ведет себя так, как вы хотели. В этом не хватает чего-то, что вам нужно?

Он компилируется с g ++ 4.3.3 и, похоже, работает нормально.

Я сделал пространство имен, чтобы поместить перечисления в другую область видимости. (чтобы красный не был взят и т. д.) Может быть, вы можете разрезать его на что-то, что вы могли бы использовать? :)

Если вам нужен Color :: Color за пределами этого пространства имен, вы можете сделать:

typedef Color::Color ColorEnum;

Но имя Color, к сожалению, занято пространством имен.

person pbos    schedule 28.10.2009
comment
Я думаю, ему нужно что-то, что может автоматизировать этот процесс (например, цвет, время года и т. Д.). - person n1ckp; 28.10.2009
comment
Я не использовал макросы таким образом, чтобы это могло расшириться. Я бы использовал решение выше, написав их вручную. Если бы ему было нужно, он мог бы написать сценарий на python или что-нибудь, что бы быстро создавало этот файл, но я не уверен, стоит ли это того. - person pbos; 28.10.2009

Я также ненавижу реальную реализацию перечислений на C ++.

  • Автоматические преобразования в целые типы
  • Без проверки значения: выполняется проверка свободного диапазона, чтобы убедиться, что значение соответствует целочисленному типу, выбранному для его хранения.
  • Сериализация: сериализация как int болезненна> вы должны сохранять старые значения, даже если они больше не используются, и вам нужно добавлять новые значения только в конце
  • Итерация невозможна, вам нужно переопределить операторы

Я закончил тем, что свернул свой собственный шаблон, чтобы попытаться автоматизировать, но на данный момент он не полностью удовлетворяет (особенно потому, что он требует специализации шаблона для каждого перечисления, и поэтому не может использоваться для перечислений, вложенных в класс / структуру: /)

Во всяком случае, я использовал следующую идею:

  • Статическая карта для хранения значений и их «значения сериализации» (в моем случае это простая строка, потому что я не очень ценю пространство и предпочитаю удобочитаемость)
  • Класс для переноса, который просто содержит итератор на карте, «конец» представляет неинициализированное / недопустимое значение.

На данный момент я использовал «истинное» перечисление, но из того, что вы сказали, я могу подумать о наличии статических экземпляров ... хотя это накладывает еще одну нагрузку на автора перечисления ...

person Matthieu M.    schedule 27.10.2009