Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Singleton class with std map of unique_ptr is throwing error on compilation

The following code is failing to compile and i am not able to figure out why!


/* --------------------------------------------------------------- */
/* Includes */
#include <iostream>
#include <map>
#include <memory>
/* --------------------------------------------------------------- */

/* Forward delcarations */
class Person;
/* --------------------------------------------------------------- */

/* Using definitions */
using PersonUptr = std::unique_ptr<Person>;
/* --------------------------------------------------------------- */

/** @brief Person class to hold a record */
class Person {
public:
    /** @brief Explicit Ctor */
    explicit Person(const std::string& name)
                : m_name(name) {}

    /** @brief Person must stay unique */
    Person(const Person&) = delete;
    Person(Person&&) = delete;
    Person& operator=(const Person&) = delete;
    Person& operator=(Person&&) = delete;

    /** @virtual Dtor */
    virtual ~Person() =  default;

    /** @brief Return name/key */
    const std::string& getName(void) const {
        return m_name;
    }
private:
    /** @brief Class member variables */
    std::string m_name = "";
};

/** @brief Singleton container for storing Person instances */
class PersonContainer {
public:
    /** @brief Virtual Dtor */
    virtual ~PersonContainer() = default;

    /** @brief Delete copy/move */
    PersonContainer(const Person&) = delete;
    PersonContainer(Person&&) = delete;
    PersonContainer& operator=(const Person&) = delete;
    PersonContainer& operator=(Person&&) = delete;

    /** @brief Singleton instance */
    static PersonContainer& getInstance(void) {
        static PersonContainer container;
        return container;
    }

    /** @brief add Person unique ptr to map */
    void addPerson(PersonUptr&& person) {
        /** FIXME Check duplicate add */
        m_person_map.insert({person->getName(), std::move(person)});
    }
private:
    /** @brief Singleton private Ctor */
    PersonContainer() = default;

    /** @brief Class members */
    std::map<std::string, PersonUptr> m_person_map;
};

/** @brief Driver code */
int main(void) {

    /** Get container handle */
    auto handle = PersonContainer::getInstance();

    return 0;
}

Error:

In file included from personal-record.cc:4:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/iostream:43:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/ios:222:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__locale:15:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/shared_ptr.h:22:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocation_guard.h:15:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator_traits.h:304:9: error: no matching function for call to 'construct_at'
        _VSTD::construct_at(__p, _VSTD::forward<_Args>(__args)...);
        ^~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__config:897:17: note: expanded from macro '_VSTD'
\#  define _VSTD std
                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__tree:2144:20: note: in instantiation of function template specialization 'std::allocator_traits<std::allocator<std::__tree_node<std::__value_type<std::string, std::unique_ptr<Person>>, void *>>>::construct<std::pair<const std::string, std::unique_ptr<Person>>, const std::pair<const std::string, std::unique_ptr<Person>> &, void, void>' requested here
    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...);
                   ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__tree:2127:29: note: in instantiation of function template specialization 'std::__tree<std::__value_type<std::string, std::unique_ptr<Person>>, std::__map_value_compare<std::string, std::__value_type<std::string, std::unique_ptr<Person>>, std::less<std::string>>, std::allocator<std::__value_type<std::string, std::unique_ptr<Person>>>>::__construct_node<const std::pair<const std::string, std::unique_ptr<Person>> &>' requested here
        __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
                            ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__tree:1274:16: note: in instantiation of function template specialization 'std::__tree<std::__value_type<std::string, std::unique_ptr<Person>>, std::__map_value_compare<std::string, std::__value_type<std::string, std::unique_ptr<Person>>, std::less<std::string>>, std::allocator<std::__value_type<std::string, std::unique_ptr<Person>>>>::__emplace_hint_unique_key_args<std::string, const std::pair<const std::string, std::unique_ptr<Person>> &>' requested here
        return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), __v).first;
               ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1318:29: note: in instantiation of member function 'std::__tree<std::__value_type<std::string, std::unique_ptr<Person>>, std::__map_value_compare<std::string, std::__value_type<std::string, std::unique_ptr<Person>>, std::less<std::string>>, std::allocator<std::__value_type<std::string, std::unique_ptr<Person>>>>::__insert_unique' requested here
            {return __tree_.__insert_unique(__p.__i_, __v);}
                            ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1339:17: note: in instantiation of member function 'std::map<std::string, std::unique_ptr<Person>>::insert' requested here
                insert(__e.__i_, *__f);
                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1147:13: note: in instantiation of function template specialization 'std::map<std::string, std::unique_ptr<Person>>::insert<std::__map_const_iterator<std::__tree_const_iterator<std::__value_type<std::string, std::unique_ptr<Person>>, std::__tree_node<std::__value_type<std::string, std::unique_ptr<Person>>, void *> *, long>>>' requested here
            insert(__m.begin(), __m.end());
            ^
personal-record.cc:43:7: note: in instantiation of member function 'std::map<std::string, std::unique_ptr<Person>>::map' requested here
class PersonContainer {
      ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/construct_at.h:39:38: note: candidate template ignored: substitution failure [with _Tp = std::pair<const std::string, std::unique_ptr<Person>>, _Args = <const std::pair<const std::string, std::unique_ptr<Person>> &>]: call to implicitly-deleted copy constructor of 'std::pair<const std::string, std::unique_ptr<Person>>'
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
                                     ^
1 error generated.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

In this line:

auto handle = PersonContainer::getInstance();

You attempt to create a copy of the singleton because auto does not deduce a reference.
You get an error because your map contains a unique_ptr and is therefore non-copyable.

In order to get the reference you need to change it to:

//---v-----------------------------------------
auto & handle = PersonContainer::getInstance();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading