another way to do this is to use a lambda. it's the same as using a separate function but puts the map's initialisation closer to the action. In this case I've used a combination of an auto& and decltype to avoid having to name the type of the map, but that's just for fun.
Note that the argument passed into the lambda is a reference to an object that has not yet been constructed at the point of the call, so we must not reference it in any way. It's only used for type deduction.
#include <memory>
#include <map>
#include <utility>
struct MyClass {};
static auto& f()
{
static std::map<int, std::unique_ptr<MyClass>> mp = [](auto& model)
{
auto mp = std::decay_t<decltype(model)> {};
mp.emplace(0, std::make_unique<MyClass>());
mp.emplace(1, std::make_unique<MyClass>());
return mp;
}(mp);
return mp;
}
int main()
{
auto& m = f();
}
Here's another way. In this case we've passed a temporary into the lambda and relied on copy elision/RVO.
#include <memory>
#include <map>
#include <utility>
struct MyClass {};
static auto& f()
{
static auto mp = [](auto mp)
{
mp.emplace(0, std::make_unique<MyClass>());
mp.emplace(1, std::make_unique<MyClass>());
return mp;
}(std::map<int, std::unique_ptr<MyClass>>{});
return mp;
}
int main()
{
auto& m = f();
}
And yet another way, using a lambda capture in a mutable lambda.
#include <memory>
#include <map>
#include <utility>
struct MyClass {};
static auto& f()
{
static auto mp = [mp = std::map<int, std::unique_ptr<MyClass>>{}]() mutable
{
mp.emplace(0, std::make_unique<MyClass>());
mp.emplace(1, std::make_unique<MyClass>());
return std::move(mp);
}();
return mp;
}
int main()
{
auto& m = f();
}