Very often, when I program, I use polymorphism because it naturally models the objects that I need. On the other hand I very often use standard containers to store these obj
How about writing a wrapper around foo that incapsulates foo* and implicitly converts to foo&?
It uses a copy semantic that calls the underlying clone on the stored object to make a deep copy. This is at least not worse than the original intent to store everything by value. If you end up storing everything as a pointer to abstract base anyway then this has the same level of indirection as a unique_ptr but is copyable (whereas unique_ptr is not). On the other hand this is less overhead than shared_ptr.
Add clone() to the abstract hierarchy:
struct foo {
virtual void print() const = 0;
virtual ~foo() {};
virtual foo* clone() = 0;
};
struct goo : public foo {
int a;
void print() const { std::cout << "goo" << std::endl; }
foo* clone() { return new goo(*this); }
};
struct moo : public foo {
int a,b;
void print() const { std::cout << "moo" << std::endl; }
foo* clone() { return new moo(*this); }
};
Define foo_w wrapper around foo, see copy-and-swap idiom.
struct foo_w {
foo_w(foo *f = nullptr) : fp(f) {}
~foo_w() { delete fp; }
foo_w(const foo_w& that) : fp(that.fp->clone()) {}
foo_w(foo_w&& that) : foo_w() { swap(*this, that); }
foo_w& operator=(foo_w rhs) {
swap(*this, rhs);
return *this;
}
friend void swap(foo_w& f, foo_w& s) {
using std::swap;
swap(f.fp, s.fp);
}
operator foo&() { return *fp; }
operator const foo&() const { return *fp; }
foo& get() { return *fp; }
const foo& get() const { return *fp; }
// if we rewrite interface functions here
// calls to get() could be eliminated (see below)
// void print() { fp->print(); };
private:
foo *fp;
};
The usage is as follows:
#include
#include
#include
// class definitions here...
int main() {
std::vector foos;
foos.emplace_back(new moo);
foos.emplace_back(new goo);
foos.emplace_back(new goo);
foos.emplace_back(new moo);
// variant 1: do it through a getter:
for(auto it = foos.begin(); it!=foos.end(); ++it) {
it->get().print();
// the presence of a proxy is almost hidden
// if we redefine interface in foo_w
// it->print();
}
// variant 2: use it through reference to foo
for(auto it = foos.begin(); it!=foos.end(); ++it) {
foo& fr = *it;
fr.print();
}
// variant 3: looks really nice with range-for
for(foo& fr : foos)
fr.print();
return 0;
}
The wrapper behavior is really up to what suits your needs. Probably if you're OK with unique_ptr being not copyable that one is a better way to go, for me it was critical so I ended up with this. Also have a look at std::reference_wrapper to store reference-like objects in the container.