Search code examples
c++c++14stdmap

C++14 Static class map initialization


right now I'm creating a static class (yes, c++ does not have static classes, but to my knowledge creating a class with a private constructor gives the same result) like the following returning to me a map:

class Foo()
{
public:
    static std::map<MyEnum, SomeInfo> getMap()
    {
        static const std::map<MyEnum, SomeInfo> fooMap
        {
            {MyEnum::Enum1, SomeInfo{ "info1", "Info 1" }},
            {MyEnum::Enum2, SomeInfo{ "info2", "Info 2" }},
        }
        return fooMap;
    }
}

struct SomeInfo
{
    std::string id;
    std::string name;
}

This method may very frequently, in my opinion this doesn't look very efficient because everytime create a new istance of a map then return it. I've tried to create a static const std::map instead and initialize it in the following way:

class Foo()
{
public:
    static const std::map<MyEnum, SomeInfo> fooMap
    {
        {MyEnum::Enum1, SomeInfo{ "info1", "Info 1" }},
        {MyEnum::Enum2, SomeInfo{ "info2", "Info 2" }},
    }
}

but this returns the following error: Static data member of type 'const std::map<MyEnum, SomeInfo>' must be initialized out of line

I've really no idea how to do that, after some research I didn't find anything really helpful..

Any guesses?

Thanks in advance to everyone!


Solution

  • You need to "define" your map after you "declared" it: See: https://en.cppreference.com/w/cpp/language/static

    #include <map>
    #include <string>
    
    struct SomeInfo
    {
        std::string id;
        std::string name;
    };
    
    enum MyEnum {
        Enum1, Enum2
    
    };
    
    class Foo
    {
    private:
        static const std::map<MyEnum, SomeInfo> fooMap;
    public:
        static std::map<MyEnum, SomeInfo> getMap()
        {
            return fooMap;
        }
    };
    
    const std::map<MyEnum, SomeInfo> Foo::fooMap = {
        {MyEnum::Enum1, SomeInfo{ "info1", "Info 1" }},
        {MyEnum::Enum2, SomeInfo{ "info2", "Info 2" }}
    };
    
    
    int main(){
        auto val = Foo::getMap()[MyEnum::Enum1];
        return 0;
    }
    

    And if you want to make your type not constructable you can delete the compiler generated default constructor via Foo() = delete; - it must not be private.