Intrusive value semantic polymorphism example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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