Saket Jalan
Saket Jalan

Reputation: 33

Initialize a const map which has shared_ptr as values

I am trying to create a const map with key as int and second value is shared_ptr to a class.

Let say, I have a class A with B, and C derived from A. I want to be able to create a map

const map<int, shared_ptr<A>> mymap

and initialize the map with the values:

{1, new B()} and {2, new C()}

But using initializer list gives error. Any help on how can I do this?

Upvotes: 3

Views: 2565

Answers (1)

Andy Prowl
Andy Prowl

Reputation: 126432

The problem is that you are trying to construct a shared_ptr implicitly from a raw pointer. You have to initialize your map this way:

const map<int, shared_ptr<A>> mymap = {
    {1, shared_ptr<B>(new B())}, 
    {2, shared_ptr<C>(new C())}
    };

Paragraph 20.7.2.2 of the C++11 Standard demands shared_ptr<>'s constructor that accept a raw pointer to be explicit:

template<typename Y> explicit shared_ptr(Y* p);

The problem is that you are trying to construct instances of std::pair<int, shared_ptr<A>> by passing a raw pointer as the second argument to the pair<>'s constructor, which accepts a shared_ptr<A>. Basically, this is the same as:

pair<int, shared_ptr<A>> mymap(1, new B()); // ERROR!
pair<int, shared_ptr<A>> mymap(1, shared_ptr<B>(new B())); // OK

This said, unless you have very good reasons to do otherwise and you really know what you are doing, it is always better to use std::make_shared<>() to create shared pointers, both because of efficiency (it performs one memory allocation instead of two) and exception-safety (it won't leak if the constructor of B or C throws an exception). Thus, your map initialization should look like:

const map<int, shared_ptr<A>> mymap = {
    {1, make_shared<B>()}, 
    {2, make_shared<C>()}
    };

Upvotes: 7

Related Questions