Переопределение оператора класса Enum

#c #enums

#c #перечисления

Вопрос:

У меня есть класс enum, определенный таким образом в MyClass.h:

 enum class SpeedMode {
  SPEED_SLOW = 0,
  SPEED_NORMAL = 1,
  SPEED_FAST = 2
};
  

В другом файле я хотел бы использовать свое перечисление в качестве int:

 void myOtherClass::myFunc(const SpeedModeamp; speed_mode) {
  int speed_as_int = speed_mode;
.
.
.
}
  

В том же файле, в котором я определил свое перечисление (MyClass.h), я пытаюсь определить переопределение оператора:

 int operator= (const SpeedModeamp; mode) {
   return static_cast<int>(mode); //The real logic is more complex and will use a switch statement
}
  

Но я получаю эту ошибку: error: 'int operator=(const SpeedModeamp;)' must be a nonstatic member function .

Если я попытаюсь обернуть его во что-то подобное struct SpeedModeUtils { } , что позволяет этому файлу компилироваться, но затем MyOtherClass выдает мне эту ошибку, когда я пытаюсь использовать переопределение: error: cannot convert 'const SpeedMode' to 'int' in initialization

Я знаю, что мог бы использовать старое неклассовое перечисление, но это большой проект, и я предпочитаю безопасность типов класса enum. Я также знаю, что могу использовать static_cast, но я бы предпочел избежать этого по очевидным причинам.

Если это не удастся, я просто использую функцию преобразования вручную, но решил, что это будет «более приятный» способ справиться с этим.

Комментарии:

1. Что такое SpeedMode ? вызывается перечисление, которое Speed не показало никакой структуры. SpeedMode

2. Кроме того, у меня есть еще один. 1) Почему вы используете enum class , а не просто enum ? Если вы используете более позднее перечисление, оно будет просто целочисленным представлением, и вы можете сказать int convertSpeedToInt(Speed mode) {return mode;}

3. Я надеюсь обеспечить безопасность типов в классе enum, хотя да, я думаю, что остановлюсь на простой вспомогательной функции, содержащей оператор switch .

4. На всякий случай, что вы имеете в виду под безопасностью типов, так это то, что вы можете избежать сравнения с другими перечислениями и целыми числами, верно?

5. Да, это в основном описывает это. Также, чтобы избежать столкновения имен, принудительно используя SpeedMode::SPEED_SLOW вместо простого использования SPEED_SLOW.

Ответ №1:

Вам нужен доступ к базовому типу данных класса enum, то есть к int . Способ сделать это — использовать std::underlying_type<T> для доступа к целочисленному значению. Способ, которым вы это делаете,:

 #include <type_traits>

auto speed_mode_as_int = static_cast<std::_underlying_type<SpeedMode>::type>(speed_mode); 
  

Я привел здесь минимальный рабочий пример, который должен помочь вам начать

 #include <type_traits>
#include <iostream>
#include <cassert>

enum class SpeedMode {
    SPEED_SLOW = 0,
    SPEED_NORMAL = 1,
    SPEED_FAST = 2
    
};

bool is_fast(const SpeedModeamp; speed_mode)
{
    auto speed_mode_as_int =
        static_cast<std::underlying_type<SpeedMode>::type>(speed_mode);

    switch(speed_mode_as_int)
    {
    case 2:
        return true;
    default:
        return false;
    }
}
    

int main(void) {

    auto mode = SpeedMode::SPEED_SLOW;

    assert(false == is_fast(mode));
    mode = SpeedMode::SPEED_NORMAL;
    assert(false == is_fast(mode));
    mode = SpeedMode::SPEED_FAST;
    assert(true == is_fast(mode));
        
    return 0; 
}
  

Я скомпилировал его со следующей строкой компиляции: clang -std=c 17 main.cpp .

Комментарии:

1. Спасибо, по сути, это то, что я закончил делать вчера. Не совсем так чисто, как я надеялся, но это хороший ответ.

Ответ №2:

Как сказал вам компилятор, вы не можете определить такой оператор присваивания. Он сказал int operator=(const SpeedModeamp;)' must be a nonstatic member function , что перечисления просто не имеют членов в C .

Комментарии:

1. Да, я понял эту часть, поэтому я попытался обернуть ее в структуру Util, но как мне сделать ее доступной для всего мира? (Или, по крайней мере, везде, где включен файл MyClass.h)

2. Не могли бы вы быть более понятными? Я понял, что вы еще не успешно внедрили Util struct , так что вы хотите сделать «глобально доступным»?

3. Как можно проще и понятнее спросить: как мне импортировать operator= override, чтобы он использовался в MyOtherClass ?

4. @Fozefy Ты этого не делаешь. Это просто невозможно.