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

6
  • 2
    How can this compile if you declare EnumClassHash in the .cpp and colours_map in the .hpp? Commented Jul 17, 2019 at 15:31
  • Please be more specific about crash happenes. Does it happen while initializing the unordered map? Commented Jul 17, 2019 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? Commented Jul 17, 2019 at 15:35
  • Seems to work fine here wandbox.org/permlink/xm37mOGjYFbOjc7I after a few fixes (missing #include, wrong place for the EnumClassHash declaration). You need to be more specific. Commented Jul 17, 2019 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 Commented Jul 17, 2019 at 15:46

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.