0

I'm having issues using an enum class as a type specifier within an unordered_map.

I've trawled the internet but had no luck with any of the solutions.

Closest example I found was at the link below, but seemingly doesn't work. Can't use enum class as unordered_map key

Running on an STM32F4103 if it matters.

foo.h

#include <cstring>
#include <unordered_map>
#include <functional>

class Foo
{
    public:
        enum class COLOURS : uint16_t
    {
        RED,
        YELLOW,
        BLUE,
        GREEN
    };
        static const std::unordered_map<COLOURS, std::string, EnumClassHash> colours_map;
};

foo.cpp

#include "foo.h"

struct EnumClassHash
{
    template <typename T>
    std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};

std::unordered_map<Foo::COLOURS, std::string, EnumClassHash> Foo::colours_map
{
    {Foo::COLOURS::RED, "red"},
    {Foo::COLOURS::YELLOW, "yellow"},
    {Foo::COLOURS::BLUE, "blue"},
    {Foo::COLOURS::GREEN, "green"}
};

The above compiles fine, I've omitted the main, but basically construct the class and get the string associated to a specified colour.

However, it crashes the chip. My suspicion is that the hash has computed incorrectly??

Complete newbie to hashing so layman's terms or a code snippet would be greatly appreciated.

TIA

EDIT:

So thank you for the help so far. Issue still persists but I can be more specific now.

The following foo.h and a corresponding empty foo.cpp compiles and runs fine:

foo.h

#include <unordered_map>
#include <cstdint>
#include <functional>
#include <string>

struct EnumClassHash
{
    template <typename T>
    std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};

class Foo {
public:
    Foo() :
        colours_map(
                    {
                        {COLOURS::RED,      "red"},
                        {COLOURS::YELLOW,   "yellow"},
                        {COLOURS::BLUE,     "blue"},
                        {COLOURS::GREEN,    "green"}
                    }
                    )
    {
        ;
    }

    enum class COLOURS: uint16_t {
        RED,
        YELLOW,
        BLUE,
        GREEN
    };
    const std::unordered_map<COLOURS, std::string, EnumClassHash> colours_map;
};

However, I really need this to be static for my application. The following, compiles fine but crashes the chip. As far as I can tell using openOCD the chip doesn't even boot. Odd given that it works fine here https://wandbox.org/permlink/xm37mOGjYFbOjc7I

foo.h

#include <unordered_map>
#include <cstdint>
#include <functional>
#include <string>

struct EnumClassHash
{
    template <typename T>
    std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};

class Foo {
public:
    enum class COLOURS: uint16_t {
        RED,
        YELLOW,
        BLUE,
        GREEN
    };
    static const std::unordered_map<COLOURS, std::string, EnumClassHash> colours_map;
};

foo.cpp

#include "foo.h"

const std::unordered_map<Foo::COLOURS, std::string, EnumClassHash> Foo::colours_map {
    {Foo::COLOURS::RED, "red"},
    {Foo::COLOURS::YELLOW, "yellow"},
    {Foo::COLOURS::BLUE, "blue"},
    {Foo::COLOURS::GREEN, "green"}
};

...I feel I am missing something very obvious. TIA

Community
  • 1
  • 1
  • 2
    How can this compile if you declare `EnumClassHash` in the `.cpp` and `colours_map` in the `.hpp`? – Holt Jul 17 '19 at 15:31
  • Please be more specific about crash happenes. Does it happen while initializing the unordered map? – 273K Jul 17 '19 at 15:34
  • What kind of crash do you get? Do you get a crash if you use a function to add each value to a map and then return that map to initialize `colours_map` with? – NathanOliver Jul 17 '19 at 15:35
  • Seems to work fine here https://wandbox.org/permlink/xm37mOGjYFbOjc7I after a few fixes (missing `#include`, wrong place for the `EnumClassHash` declaration). You need to be more specific. – Holt Jul 17 '19 at 15:37
  • my mistake, bad copy and paste. Apologies. EnumClassHash is in the .h file. Looks like it may be something else crashing the chip in that case. @Holt thanks for that snippet, wasn't aware of that website. Great tool! Will work from there. Many thanks everyone – GreenaGiant Jul 17 '19 at 15:46
  • All, have edited the OC to add more detail and diagnosis. Issue persists – GreenaGiant Jul 18 '19 at 09:08

1 Answers1

0

Thanks all for the help in the comments.

Just wanted to close this and say that the code worked fine with your suggestions...off chip.

The issue seems to be that when the maps were declared as a static const, when the object using them is created, it then created a copy of these maps (I assume on the stack??). When declared as a const only, the object using them just referenced the flash and didn't create a second "local" copy. Very odd, not sure why, seems to be counterintuative to be regarding the definition of static but whatever. Probably my misunderstanding!

Works well as just a const and I am unlikely to have more than one instance of the object so it's not too big an issue it not being static too.

Thanks again.