Skip to content

Instantly share code, notes, and snippets.

@sean-parent
Last active November 28, 2016 08:14
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sean-parent/6798797 to your computer and use it in GitHub Desktop.
Save sean-parent/6798797 to your computer and use it in GitHub Desktop.
Intrusive value semantic polymorphism example.
#include <memory>
using namespace std;
template <typename C> // Concept base class
class any {
public:
template <typename T>
any(T x) : self_(new model<T>(move(x))) { }
template <typename T, typename F>
any(unique_ptr<T>&& x, F cpy) : self_(new model_unique<T, F>(move(x), move(cpy))) { }
any(const any& x) : self_(x.self_->copy()) { }
any(any&&) noexcept = default;
any& operator=(const any& x) { any tmp = x; *this = move(tmp); return *this; }
any& operator=(any&&) noexcept = default;
C* operator->() const { return &self_->dereference(); }
C& operator*() const { return self_->dereference(); }
private:
struct regular {
virtual regular* copy() const = 0;
virtual C& dereference() = 0;
};
template <typename T>
struct model : regular {
model(T x) : data_(move(x)) { }
regular* copy() const { return new model(*this); }
C& dereference() { return data_; }
T data_;
};
template <typename T, typename F>
struct model_unique : regular {
model_unique(unique_ptr<T>&& x, F cpy) : data_(move(x)), copy_(move(cpy)) { }
regular* copy() const { return new model_unique(copy_(*data_), copy_); }
C& dereference() { return *data_; }
unique_ptr<T> data_;
F copy_;
};
unique_ptr<regular> self_;
};
/**************************************************************************************************/
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class shape {
public:
virtual void draw(ostream& out, size_t position) const = 0;
};
class square : public shape {
void draw(ostream& out, size_t position) const
{ out << string(position, ' ') << "square" << endl; }
};
class circle : public shape {
void draw(ostream& out, size_t position) const
{ out << string(position, ' ') << "circle" << endl; }
};
int main() {
any<shape> x = { unique_ptr<square>(new square()),
[](const square& x) { return unique_ptr<square>(new square()); } };
vector<any<shape>> a = { square(), circle(), x };
for (const auto& e : a) e->draw(cout, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment