Reputation: 109
I am trying to implement serialization into my project. My problem is that when I'm trying to deserialize objects, I'm getting error like:
/usr/include/c++/5/ext/new_allocator.h:120:4: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Employee; _Dp = std::default_delete<Employee>]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
EDIT: I added hireIntern
and employeeMenu
functions and I reduced some unnecessary code.
class Employee {
protected:
int employeeID;
std::string Name;
std::string Surname;
int Salary;
bool Hired;
public:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive & ar, const unsigned int file_version) {
ar & employeeID;
ar & Name;
ar & Surname;
ar & Salary;
ar & Hired;
}
virtual ~Employee();
Employee();
Employee(const std::string &, const std::string &);
.cpp
#include "Employee.h"
Employee::~Employee() = default;
Employee::Employee() = default;
Employee::Employee(const std::string &newName, const std::string &newSurname) : Name(newName), Surname(newSurname) {}
Derived, "Intern.h"
class Intern : public Employee {
public:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive & ar, const unsigned int file_version) {
ar & boost::serialization::base_object<Employee>(*this);
ar & Status;
}
std::string Status = "Intern";
Intern();
~Intern();
Intern(const std::string &, const std::string &);
};
BOOST_CLASS_EXPORT_KEY(Intern);
.cpp
#include "Intern.h"
BOOST_CLASS_EXPORT_IMPLEMENT(Intern);
Intern::Intern() = default;
Intern::~Intern() = default;
Intern::Intern(const std::string &newName, const std::string &newSurname) : Employee(newName, newSurname) {}
Commented lines at the start causing error with deserialization.
When I ignore them, serialization implemented in case 3:
works fine.
The problem is, I also want to load objects into vector from .txt file at start.
void mainMenu() {
//std::ifstream ifs("database");
//boost::archive::text_iarchive ia(ifs);
vector<unique_ptr<Employee>> Firm;
//ia >> boost::serialization::make_nvp("root", Firm);
...
switch (option) {
case 1:
hireIntern(Firm);
break;
case 2:
employeeMenu(Firm);
break;
case 3:
{
std::ofstream ofs("database");
boost::archive::text_oarchive oa(ofs);
oa << boost::serialization::make_nvp("root", Firm);
return;
}
...
.
void hireIntern(vector<unique_ptr<Employee>>& sourceEmployee) {
...
sourceEmployee.emplace_back(new Intern(fillName, fillSurname));
. In functions called in employeeMenu
I'm just editting some Firm
vector of objects fields like sourceEmployee[index]->setSalary(sourceEmployee[index]->getSalary() + 1000);
void employeeMenu(vector<unique_ptr<Employee>>& sourceEmployee) {
...
switch (option) {
case 1:
Promote(sourceEmployee);
break;
case 2:
Demote(sourceEmployee);
break;
case 3:
fireEmployee(sourceEmployee);
break;
case 4:
employeeShowcase(sourceEmployee);
break;
case 5:
showHiredEmployees(sourceEmployee);
break;
case 6:
showFiredEmployees(sourceEmployee);
When I compile code with these lines I'm getting following error:
/usr/local/bin/cmake --build /home/max/c++/PROJEKT/cmake-build-debug --target PROJEKT -- -j 2
Scanning dependencies of target PROJEKT
[ 12%] Building CXX object CMakeFiles/PROJEKT.dir/mainMenu.cpp.o
In file included from /usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h:33:0,
from /usr/include/c++/5/bits/allocator.h:46,
from /usr/include/c++/5/string:41,
from /usr/include/c++/5/bits/locale_classes.h:40,
from /usr/include/c++/5/bits/ios_base.h:41,
from /usr/include/c++/5/ios:42,
from /usr/include/c++/5/istream:38,
from /usr/include/c++/5/fstream:38,
from /home/max/c++/PROJEKT/Employee.h:8,
from /home/max/c++/PROJEKT/manageDatabase.h:8,
from /home/max/c++/PROJEKT/mainMenu.cpp:5:
/usr/include/c++/5/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::unique_ptr<Employee>; _Args = {const std::unique_ptr<Employee, std::default_delete<Employee> >&}; _Tp = std::unique_ptr<Employee>]’:
/usr/include/c++/5/bits/alloc_traits.h:530:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::unique_ptr<Employee>; _Args = {const std::unique_ptr<Employee, std::default_delete<Employee> >&}; _Tp = std::unique_ptr<Employee>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::unique_ptr<Employee> >]’
/usr/include/c++/5/bits/stl_vector.h:917:30: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<Employee>; _Alloc = std::allocator<std::unique_ptr<Employee> >; std::vector<_Tp, _Alloc>::value_type = std::unique_ptr<Employee>]’
/usr/local/include/boost/serialization/vector.hpp:102:13: required from ‘void boost::serialization::load(Archive&, std::vector<U, Allocator>&, unsigned int, mpl_::false_) [with Archive = boost::archive::text_iarchive; U = std::unique_ptr<Employee>; Allocator = std::allocator<std::unique_ptr<Employee> >; mpl_::false_ = mpl_::bool_<false>]’
/usr/local/include/boost/serialization/vector.hpp:173:9: required from ‘void boost::serialization::load(Archive&, std::vector<U, Allocator>&, unsigned int) [with Archive = boost::archive::text_iarchive; U = std::unique_ptr<Employee>; Allocator = std::allocator<std::unique_ptr<Employee> >]’
/usr/local/include/boost/serialization/split_free.hpp:58:13: required from ‘static void boost::serialization::free_loader<Archive, T>::invoke(Archive&, T&, unsigned int) [with Archive = boost::archive::text_iarchive; T = std::vector<std::unique_ptr<Employee> >]’
/usr/local/include/boost/serialization/split_free.hpp:74:18: [ skipping 22 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/local/include/boost/archive/detail/iserializer.hpp:618:18: required from ‘void boost::archive::load(Archive&, T&) [with Archive = boost::archive::text_iarchive; T = const boost::serialization::nvp<std::vector<std::unique_ptr<Employee> > >]’
/usr/local/include/boost/archive/detail/common_iarchive.hpp:66:22: required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = const boost::serialization::nvp<std::vector<std::unique_ptr<Employee> > >; Archive = boost::archive::text_iarchive]’
/usr/local/include/boost/archive/basic_text_iarchive.hpp:71:9: required from ‘void boost::archive::basic_text_iarchive<Archive>::load_override(T&, int) [with T = const boost::serialization::nvp<std::vector<std::unique_ptr<Employee> > >; Archive = boost::archive::text_iarchive]’
/usr/local/include/boost/archive/text_iarchive.hpp:92:52: required from ‘void boost::archive::text_iarchive_impl<Archive>::load_override(T&, int) [with T = const boost::serialization::nvp<std::vector<std::unique_ptr<Employee> > >; Archive = boost::archive::text_iarchive]’
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:60:9: required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = const boost::serialization::nvp<std::vector<std::unique_ptr<Employee> > >; Archive = boost::archive::text_iarchive]’
/home/max/c++/PROJEKT/mainMenu.cpp:16:54: required from here
/usr/include/c++/5/ext/new_allocator.h:120:4: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Employee; _Dp = std::default_delete<Employee>]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /usr/include/c++/5/bits/locale_conv.h:41:0,
from /usr/include/c++/5/locale:43,
from /usr/include/c++/5/iomanip:43,
from /usr/local/include/boost/archive/basic_text_oprimitive.hpp:27,
from /usr/local/include/boost/archive/text_oarchive.hpp:30,
from /home/max/c++/PROJEKT/Employee.h:9,
from /home/max/c++/PROJEKT/manageDatabase.h:8,
from /home/max/c++/PROJEKT/mainMenu.cpp:5:
/usr/include/c++/5/bits/unique_ptr.h:356:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^
CMakeFiles/PROJEKT.dir/build.make:114: recipe for target 'CMakeFiles/PROJEKT.dir/mainMenu.cpp.o' failed
make[3]: *** [CMakeFiles/PROJEKT.dir/mainMenu.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/PROJEKT.dir/all' failed
make[2]: *** [CMakeFiles/PROJEKT.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/PROJEKT.dir/rule' failed
make[1]: *** [CMakeFiles/PROJEKT.dir/rule] Error 2
Makefile:118: recipe for target 'PROJEKT' failed
make: *** [PROJEKT] Error 2
Upvotes: 0
Views: 70
Reputation: 8217
I think that in your case you should use shared_ptr
instead of unique_ptr
, because you are sharing the pointers ownership between your main
function, std::vector
container, hireIntern
function, employeeMenu
function and also boost::serialization
routines. unique_ptr
should only be used, when at the time just one unique_ptr
instance is pointing at the same memory - i.e. it has a unique ownership. If you insist on using unique_ptr
with containers and you wish to pass that container to the functions, read this question to learn how to use move semantics (because copy constructor of unique_ptr
is deleted). Otherwise, I recommend shared_ptr
.
EDIT ==== according to your comment
In the stacktrace that you provided you can find:
/usr/include/c++/5/bits/stl_vector.h:917:30: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<Employee>; _Alloc = std::allocator<std::unique_ptr<Employee> >; std::vector<_Tp, _Alloc>::value_type = std::unique_ptr<Employee>]’
/usr/local/include/boost/serialization/vector.hpp:102:13: required from ‘void boost::serialization::load(Archive&, std::vector<U, Allocator>&, unsigned int, mpl_::false_) [with Archive = boost::archive::text_iarchive; U = std::unique_ptr<Employee>; Allocator = std::allocator<std::unique_ptr<Employee> >; mpl_::false_ = mpl_::bool_<false>]’
You can see that boost::serialization
routine instantiated by you with the type std::vector<std::unique_ptr<Employee>, "standard allocator">
is trying to execute void std::vector<_Tp, _Alloc>::push_back(const value_type&)
which is strictly forbidden for the type std::unique_ptr
. I guess that problem appears upon text_iarchive
instantiation - as name suggests it is an input class and it probably calls push_back
at some point (it can easily be confirmed, just scan quickly the boost code).
So, again, if you plan to store a smart pointer in the container that usually means that you don't really want to use std::unique_ptr
for that purpose.
Upvotes: 2