2

I am trying to std::map, with an enum class and a std::string but I am getting some error. I am using gcc 4.4.7 with -std=c++0x (this is fixed)

At .h file:

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

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

At .cpp file:

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

The method to allow a state transitionis like:

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;
}

When compilling, I get next error: error: invalid operands of types 'state_t' and 'state_t' to binary 'operator<'

If I change the enum class state_t to enum state_t it works. Is there any way to find in the map with an enum class?

Thanks in advance.

user2357667
  • 79
  • 1
  • 1
  • 9
  • 1
    Did you misspell `<<` as `<`? – Kerrek SB Feb 24 '17 at 11:11
  • No, I have checked it – user2357667 Feb 24 '17 at 11:14
  • Oh, so this question has nothing to do with `cout` at all? Does just defining the map work at all? – Kerrek SB Feb 24 '17 at 11:19
  • 3
    well map requires < operator for key type. you can see example at http://stackoverflow.com/questions/15451382/implementation-of-operators-for-enum-class – Andrew Kashpur Feb 24 '17 at 11:20
  • Cannot reproduce, tested on avalaible compilers on ideone. One [example](http://ideone.com/ascl6q). (Check answer from @Evgeny to see misspells and missed commas) – Yuriy Ivaskevych Feb 24 '17 at 11:30
  • @AndrewKashpur hmm, true, but according to [docs](http://en.cppreference.com/w/cpp/language/enum) the underlying type for `enum class` is `int` (if not explicitly specified smth else), so there probably should be something else. – Yuriy Ivaskevych Feb 24 '17 at 11:33
  • No, this question has nothing to do with cout, sorry. I can not edit the question. – user2357667 Feb 24 '17 at 11:34
  • Please provide your compiler version and used flag. With `GNU GCC 5.4.0 with -std=c++11` it works fine. – ashiquzzaman33 Feb 24 '17 at 11:38
  • gcc version 4.4..7 with -std=c++0x. This is fixed. I can not modify it – user2357667 Feb 24 '17 at 11:40
  • Then change the code to use `enum` in place of `enum class`, as your compiler (version and usage) *doesn't support that language feature* – Caleth Feb 24 '17 at 12:16
  • @Caleth That isn't really an acceptable answer, given the fact that the problem can be worked around by defining the missing operators yourself. The same applies to bit flags enums, which don't have compiler support at all (for pretty obvious reasons), and therefore require user intervention to work. – Tom Lint Oct 22 '18 at 11:45

2 Answers2

3

The following code works just fine (on Visual Studio 2015 (v140); which compiler is used in your case?):

#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, there is a misspell "unkmown" in the state_t.

Evgeny
  • 305
  • 3
  • 16
2

I assume the GCC compiler version you use does not support all of the infrastructure associated with enum classes. You'll therefore need to implement the missing operators yourself, as shown below:

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);
}

In C++11, these functions are likely implemented via template specialization, using std::underlying_type for the static_cast and qualifiers tying them specifically to enum classes, some of which are probably not available under -std=c++0x for your specific compiler version

Tom Lint
  • 483
  • 5
  • 13