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.
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 the std::map
member in the singleton (m_person_map
) contains unique_ptr
s and is therefore non-copyable.
In order to get the reference you need to change it to:
//---v-----------------------------------------
auto & handle = PersonContainer::getInstance();