Reputation: 139
#include <iostream>
#include <memory>
#include <vector>
#include <utility>
#include <map>
class IOutput{
public:
virtual std::ostream& print(std::ostream& out) const = 0;
virtual std::unique_ptr<IOutput> clone() const = 0;
virtual ~IOutput() = default;
};
std::ostream& operator<<(std::ostream& out, const IOutput& ser) {
ser.print(out);
return out;
}
class String : public IOutput {
private:
std::string m_str;
public:
String( std::string str )
: m_str(std::move(str))
{}
std::ostream& print(std::ostream& out) const override {
out << m_str;
return out;
}
std::unique_ptr<IOutput> clone() const override { return std::make_unique<String>(*this); }
};
class List : public IOutput {
private:
std::vector<std::unique_ptr<IOutput>> m_elements;
public:
std::ostream& print(std::ostream& out) const override {
}
std::unique_ptr<IOutput> clone() const override {
return std::make_unique<List>(*this);
}
};
int main () {
String s {"string s"};
String s2 {"string s2"};
String s3 {"string s3"};
String s4 {"string s4"};
return 0;
}
Error
/usr/include/c++/7/bits/stl_construct.h:75: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = IOutput; _Dp = std::default_delete<IOutput>]’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I found out that this error occurs only if I have std::vector<std::unique_ptr<IOutput>>
in List
. It looks like I am copying that vector when I am calling std::make_unique<List>(*this)
in clone , which means it has to copy each element from that vector, which in our case (unique_ptr) is forbidden.
How to solve this?
Upvotes: 3
Views: 428
Reputation: 139
Alternative solution without std::transform
List(const List& other)
{
m_elements.reserve(other.m_elements.size());
for (const auto& x: other.m_elements) {
m_elements.emplace_back(x->clone());
}
}
Upvotes: 1
Reputation: 1461
IOutput
has a clone()
member function. You should make a new List
that contains clones of the elements of the vector.
Upvotes: 0
Reputation: 170084
The compiler cannot generate a copy constructor, because the vector member is non-copyable. If you wish to support copying, you need to implement it yourself, for instance:
List(List const& other) : m_elements(other.m_elements.size()) {
std::transform(begin(other.m_elements), end(other.m_elements), begin(m_elements),
[](std::unique_ptr<IOutput> const& o_ptr) {
return o_ptr->clone();
}
);
}
Upvotes: 6