Search code examples
c++unique-ptrinitializer-liststdmove

using an initializer list where the values contain unique_ptr member variables


I have a class that contains a unique_ptr. I want to place instances of this class inside a container (specifically std::map). This works using std::move and .emplace however, I would like to perform all this initialization within the container's initializer list. Is this possible?

I suspect Foo gets initialized in the initializer list then copied which is causing the problem. I've tried added a std::move in the initializer list but that hasn't solved the problem.

class Foo
{
public:
  std::unique_ptr<std::string> my_str_ptrs;
}

Compilation Fails "attempting to access a deleted function". This is an example of what I want to do

std::map<std::string, Foo> my_map{
  {"a", Foo{}}
};

Compilation Succeeds

std::map<std::string, Foo> my_map;
my_map.emplace("a", Foo{});

Solution

  • It's fault of std::initializer_list, if you look at it's begin/end member functions, they return const T*, which means it will force std::map to try use the copy constructor of your Foo, which is deleted as std::unique_ptr can not be copied.

    This issue is not unique to std::map, any container which allows you to initialize it with std::initializer_list will really copy the arguments from an initializer list.

    The C++ standard requires that during such initialization there's a temporary const T[N] array, which the std::initializer_list points to, const disables moves from it.