Search code examples
c++c++14shared-ptr

How to call implicitly constructor of value wrapped in shared_ptr which is placed in std::map collection


I'm working with code generator where I can't obtain directly classname of the value which is wrapped in shared_ptr and placed in std::map.

I came to a situation where I need to create new map object but without access to classname I can't perform a valid object constructor call. I tried with the map operator at[], which calls the value constructor, but it calls shared_ptr<T> constructor and the object inside stays uninitialized.

Here the example:

#include <iostream>
#include <map>
#include <memory>

class A
{
public:
    A() { std::cout << "A"; }
    int getMember() const { return m_member; }
private:
    int m_member = 1;
};

int main()
{
    std::map<int, A> mapIntToA;
    std::map<int, std::shared_ptr<A>> mapIntToAptr;

    mapIntToA[1]; // runs A constructor
    std::cout << mapIntToA[1].getMember();
    
    mapIntToAptr[1]; // runs shared_ptr constructor
    // cant call methods of uninitalized object
    // std::cout << mapIntToAptr[1]->getMember();
    
    // this init works, but I can't use classname 'A' in my code generator
    // mapIntToAptr[1] = std::make_shared<A>();
    
    return 0;
}

Solution

  • You can use the member types of std::map and std::shared_ptr to get the type of the element.

    Something like

    using type = typename std::map<int, std::shared_ptr<A>>::mapped_type::element_type;
    mapIntToAptr[1] = std::make_shared<type>();