Как класс std::map‹enum, std::string›?

Я пытаюсь использовать std::map с классом enum и std::string, но получаю ошибку. Я использую gcc 4.4.7 с -std=c++0x (это исправлено)

В файле .h:

enum class state_t{
    unknown,
    off,
    on,
    fault
};

typedef std::map<state_t,std::string> statemap_t;

В файле .cpp:

statemap_t state={
   {state_t::unknown,"unknown"}
   {state_t::off,"off"}
   {state_t::on,"on"}
   {state_t::fault,"fault"}
}

Метод разрешения перехода состояния выглядит следующим образом:

Foo::allowStateChange(const state_t localState, const state_t globalState, const state_t newState){
    //Some code to verify if the state transition is allowed.
    std::cout << "Device Local State:" << state.find(localState)->second << "Device Global State:" << state.find(globalState)->second << "Device New State:" << state.find(newState)->second << std::endl;
}

При компиляции я получаю следующую ошибку: ошибка: недопустимые операнды типов «state_t» и «state_t» для двоичного «оператора‹»

Если я изменю enum class state_t на enum state_t, это сработает. Есть ли способ найти на карте класс перечисления?

Заранее спасибо.


person user2357667    schedule 24.02.2017    source источник
comment
Вы неправильно написали << как <?   -  person Kerrek SB    schedule 24.02.2017
comment
Нет, я проверил это   -  person user2357667    schedule 24.02.2017
comment
О, так этот вопрос вообще не имеет ничего общего с cout? Работает ли вообще простое определение карты?   -  person Kerrek SB    schedule 24.02.2017
comment
карта скважин требует оператора ‹ для типа ключа. вы можете увидеть пример в stackoverflow.com/questions /15451382/   -  person Andrew Kashpur    schedule 24.02.2017
comment
Невозможно воспроизвести, проверено на доступных компиляторах на ideone. Один пример. (Проверьте ответ @Evgeny, чтобы увидеть опечатки и пропущенные запятые)   -  person Yuriy Ivaskevych    schedule 24.02.2017
comment
@AndrewKashpur хм, правда, но, согласно документам, базовым типом для enum class является int (если явно не указано что-то еще), поэтому, вероятно, должно быть что-то еще.   -  person Yuriy Ivaskevych    schedule 24.02.2017
comment
Нет, этот вопрос не имеет отношения к cout, извините. Не могу отредактировать вопрос.   -  person user2357667    schedule 24.02.2017
comment
Укажите версию компилятора и используемый флаг. С GNU GCC 5.4.0 with -std=c++11 работает нормально.   -  person ashiquzzaman33    schedule 24.02.2017
comment
gcc версии 4.4..7 с параметром -std=c++0x. Это исправлено. я не могу его изменить   -  person user2357667    schedule 24.02.2017
comment
Затем измените код, чтобы использовать enum вместо enum class, поскольку ваш компилятор (версия и использование) не поддерживает эту языковую функцию.   -  person Caleth    schedule 24.02.2017
comment
@Caleth Это не совсем приемлемый ответ, учитывая тот факт, что проблему можно решить, самостоятельно определив отсутствующие операторы. То же самое относится к перечислениям битовых флагов, которые вообще не поддерживаются компилятором (по довольно очевидным причинам) и, следовательно, требуют вмешательства пользователя для работы.   -  person Tom Lint    schedule 22.10.2018


Ответы (2)


Следующий код отлично работает (в Visual Studio 2015 (v140); какой компилятор используется в вашем случае?):

#include <string>
#include <iostream>
#include <map>

using namespace std;

enum class state_t {
    unknown,
    off,
    on,
    fault
};

typedef std::map<state_t, std::string> statemap_t;

statemap_t state = {
    { state_t::unknown,"unknown" },
    { state_t::off,"off"},
    { state_t::on,"on"},
    { state_t::fault,"fault"}
};

void allowStateChange(const state_t localState, const state_t globalState,     const state_t newState) {
    //Some code to verify if the state transition is allowed.
    std::cout 
        << "Device Local State:" 
        << state.find(localState)->second 
        << ", Device Global State:" 
        << state.find(globalState)->second 
        << ", Device New State:" 
        << state.find(newState)->second 
        << std::endl;
}

int main()
{
    allowStateChange(state_t::on, state_t::off, state_t::fault);
    return 0;
}

BWT, в state_t есть опечатка «unkmown».

person Evgeny    schedule 24.02.2017
comment
В коде все в порядке, это просто опечатка, я не копировал код - person user2357667; 24.02.2017
comment
Я использую gcc 4.4.7 (RedHat 4.4.7-4). Но я не могу изменить версию gcc - person user2357667; 24.02.2017
comment
gcc 4.4.7, вероятно, довольно стар для поддержки классов enum. Возможно, вам придется вернуться к простым перечислениям. - person stefaanv; 24.02.2017

Я предполагаю, что используемая вами версия компилятора GCC не поддерживает всю инфраструктуру, связанную с классами enum. Поэтому вам нужно будет реализовать отсутствующие операторы самостоятельно, как показано ниже:

inline bool operator <(const state_t left, const state_t right)
{
    return static_cast<int>(left) < static_cast<int>(right);
}

inline bool operator >(const state_t left, const state_t right)
{
    return static_cast<int>(left) > static_cast<int>(right);
}

В C++11 эти функции, вероятно, реализованы через специализацию шаблона, используя std::underlying_type для static_cast и квалификаторы, связывающие их специально с классами enum, некоторые из которых, вероятно, недоступны в -std=c++0x для вашего конкретного случая. версия компилятора

person Tom Lint    schedule 22.10.2018