Search code examples
c++initializationc++14static-order-fiasco

In C++, can I safely initialize an unordered_map with values from different files?


Imagine code like this:

std::unordered_map<std::string, std::function<Foo *()>> FooFactory;
void registerFoo(std::string name, std::function<Foo *()> factory)
{
    FooFactory.emplace(name, factory);
}

If I now would write code like this in another file:

static bool Baz = [](){ registerFoo("baz", []() { return new BazFoo(); })}();

And yet another:

static bool Bar = [](){ registerFoo("bar", []() { return new BarFoo(); })}();

In this case registerFoo is called as the program initializes, but FooFactory is then zeroed out, so the registered functions disappear.

Is there a way to make this work in a safe, compiler-independent way (for c++14)?


Solution

  • You could stick the factory itself inside of a function:

    std::unordered_map<std::string, std::function<Foo *()>>& getFactory() {
        static std::unordered_map<std::string, std::function<Foo *()>> FooFactory;
        return FooFactory;
    }
    

    Which your registration function can go through:

    void registerFoo(std::string name, std::function<Foo *()> factory)
    {
        getFactory().emplace(name, factory);
    }
    

    This should guarantee ordering.