C ++ std :: unique_ptr stored in std :: map, using a poorly formed remote function

I have the following code that will not compile, but on Friday, and I'm a little worn out.

#include <string> #include <memory> #include <utility> #include <map> template< typename T, typename ...Args > std::unique_ptr< T > make_unique( Args && ...args ) { return std::unique_ptr< T >( new T( std::forward< Args >( args )... ) ); } struct A { }; std::map< std::string, std::unique_ptr< A > > _map = { { "A", make_unique< A >() } }; // <-- ERROR!! 

The following compilation no problem

 int main() { std::pair< std::string, std::unique_ptr< A > > p { "B", make_unique< A >() }; _map.insert( std::make_pair( "C", make_unique< A >() ) ); } 

The error I get (rude, like remote g ++ fluff)

 use of deleted function 'constexpr std::pair<...>( const st::pair<...> & ) 'constexp std::pair<...>::pair( const std::pair<...> & ) is implicitly deleted because the default definition would be illegal. 

Argghh !! Just read this in the C ++ 11 standard.

When an aggregate is initialized with a list of initializers, as specified in 8.5.4, the elements of the list of initializers are taken as initializers for members of the aggregate, increasing the index or order of members. Each member copies-initializes from the corresponding initialization clause

bummer !!!

Does anyone know if this is simply not possible with initialization lists?

+7
c ++ dictionary unique-ptr
source share
1 answer

You can do nothing: the elements in the list of initializers are copied. This will not be combined with classes that only have movement.

There is a way around this β€œdefect”, but reading it is not very pleasant; you decide

 using map_type = std::map< std::string, std::unique_ptr< A > >; using pair_type = map_type::value_type; pair_type elements[] = { { "A", std::make_unique< A >() }, { "B", std::make_unique< A >() } }; map_type myMap { std::make_move_iterator( begin(elements) ), std::make_move_iterator( end(elements) ) }; 

which will make myMap iterate over the range and move the elements inside, not copy. The method has been graciously accepted from this other question.

+5
source share

All Articles