Как реализовать enum с областью видимости в C ++ 98 и может использоваться как класс enum в C ++ 11? - PullRequest
1 голос
/ 17 апреля 2020

В C ++ 11 у нас есть enum с областью видимости, и мы можем использовать его следующим образом.

#include <iostream>
enum class Color
{
    RED,
    BLUE,
};
int main()
{
    Color color = Color::RED;
    if (color == Color::RED)
    {
        std::cout << "red" << std::endl;
    }
    return 0;
}

Я уже использовал enum с областью видимости везде в моем проекте.

Сейчас Я должен перейти на C ++ 98, чтобы enum с областью действия больше не мог использоваться.

Как я могу реализовать enum с областью действия в C ++ 98 и использовать так же, как в C ++ 11 ?

Если метод навесного оборудования сложный, можем ли мы извлечь его из шаблона?

Перейдите по ссылке, уже рассказавшей о некоторой технике, но не так просто, как C ++ 11.

Как использовать перечисления в C ++

Например:

namespace Color
{
enum MyColor
{
    RED,
    BLUE,
};
}

Спасибо за ваше время.

Ответы [ 2 ]

2 голосов
/ 17 апреля 2020

Обычный способ эмулировать перечисления с областью действия до C ++ 11 - объявлять перечисление без сферы действия в объявлении класса:

#include <iostream>

struct Color {
   enum MyColor {
      kRed,
      kBlue
   };
};

int main() {
    const Color::MyColor color = Color::kRed;
    if (color == Color::kRed)
    {
        std::cout << "red" << std::endl;
    }
}

или, как незначительный вариант, для некоторой краткости на возможная стоимость некоторой путаницы (то есть на сайте использования: «как соотносятся MyColor и Color?»):

#include <iostream>

struct Color {
   enum MyColorImpl {
      kRed,
      kBlue
   };
};

typedef Color::MyColorImpl MyColor;

int main() {
    const MyColor color = Color::kRed;
    if (color == Color::kRed)
    {
        std::cout << "red" << std::endl;
    }
}

Конечно, вы также можете использовать подход к определению пространства имен, показанный в ваш вопрос, но он связан с потенциальной проблемой: пространство имен может быть расширено в другом месте вашей кодовой базы, что, в свою очередь, может привести к неожиданному ( ожиданиям разработчика ) поведению; например, ваше эмулированное перечисление scoped-enum может начать вести себя как объединение нескольких различных перечислений, не относящихся к области.

#include <iostream>

namespace color {

enum MyColor {
   kRed,
   kBlue
};

}

namespace color {

enum CarColor {
   kAbsolutelyNotRed
};

}

int main() {
    const color::MyColor color = color::kRed;
    // At best, a -Wenum-compare warning.
    if (color == color::kAbsolutelyNotRed)
    {
        // At worst, a critical logical fault.
        std::cout << "absolutely not red (ups, actually red)" << std::endl;
    }
}
0 голосов
/ 18 апреля 2020

Поскольку drfi уже дает подробное объяснение, я все же даю здесь другую перспективу для решения проблемы.

Мы можем использовать класс для реализации перечисления и поддержки строгой проверки типов.

код изменен из примера class Month в книге Effective C++ 3rd: Item 18

#include <iostream>
class Color
{
public:
    static Color RED()
    {
        return Color(0);
    }
    static Color BLUE()
    {
        return Color(1);
    }
    bool operator==(const Color &rhs) const
    {
        return this->value == rhs.value;
    }
    bool operator!=(const Color &rhs) const
    {
        return !(*this == rhs);
    }

private:
    explicit Color(int value_) : value(value_) {}
    int value;
};

int main()
{
    Color color = Color::RED();
    if (color == Color::RED())
    {
        std::cout << "red" << std::endl;
    }
    return 0;
}
...