Доступ к значениям перечисления с помощью '::' в С++

У меня есть класс вроде следующего:

class Car  
{  
public:  
    Car();  
    // Some functions and members and <b>enums</b>  
    enum Color
    {
        Red,
        Blue,
        Black
    };  
    Color getColor();
    void setColor(Color);  
private:  
    Color myColor;
}

Я хочу:

  • доступ к значениям Color как Color::Red. Это действительно трудно понять код, когда используется Car::Red, когда класс имеет много перечислений, подклассы и т.д.
  • использовать тип Color как аргумент функции или возвращаемое значение
  • использовать тип переменной Color в switch

Я знаю 3 частичных решения:

  • Использование встроенного класса Color и перечисление в нем
  • Использование встроенного пространства имен Color и перечисление в нем
  • Использование enum class
Решения

1 и 2 решают проблему присоединения Color::Red, но я не могу использовать такие функции, как Color getColor() и void setColor(Color).

Решение

3 имеет проблему: VS2010 не поддерживает enum class. GCC v.4.1.2 тоже не поддерживает. Я не знаю о более поздних версиях gcc.

Да, я работаю над кросс-платформенным проектом.
Я нашел это решение, но похоже... тяжелое.
Я надеюсь, что кто-то может мне помочь здесь:)

Ответ 1

В текущем C++ (т.е. C++ 11 и выше) вы уже можете получить доступ к значениям перечисления следующим образом:

enum Color { Red };
Color c = Color::Red;
Color d = Red;

Вы можете пойти дальше и навязать использование этой нотации:

enum class Color { Red };
Color c = Color::Red;
// Color d = Red;   <--  error now

А теперь вы должны определить базовый тип, который ранее был возможен только с хакерским кодом (FORCEDWORD или кем-то еще?):

enum class Color : char { Red };

Ответ 2

Назовите enum внутри вложенного класса (в качестве примера):

class Car
{
public:
    struct Color
    {
        enum Type
        {
            Red,
            Blue,
            Black
        };
    };

    Color::Type getColor();
    void setColor(Color::Type);
};

Ответ 3

Когда я хочу сделать что-то подобное, я, как правило, использую пространство имен и typedef за пределами пространства имен (хотя обычно я делаю это глобально, а не внутри класса). Что-то вроде этого:

namespace colors 
{
    enum Color 
    {
        Red,
        Blue
        ...
    }
}
typedef colors::Color Color;

Таким образом вы используете пространство имен для получения фактических цветов, но сам тип Color по-прежнему доступен по всему миру:

Color myFav = colors::Red;