Skip to content

Instantly share code, notes, and snippets.

@2bdkid
Last active September 18, 2019 00:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2bdkid/45663cbf281405b4e0fc0980dfe8a126 to your computer and use it in GitHub Desktop.
Save 2bdkid/45663cbf281405b4e0fc0980dfe8a126 to your computer and use it in GitHub Desktop.
spooky runtime polymorphism
#include <memory>
#include <vector>
#include <iostream>
#include <cstddef>
#include <string>
/// draw
///
/// draw a fundamental type
/// @param[in] t Object to draw
/// @param[in] out Output stream to write to
/// @param[in] position Spacing from left side
template <typename T>
void draw(const T& t, std::ostream& out, std::size_t position) {
out << std::string(position, ' ') << t << '\n';
}
/// object_t
///
/// Represents a document object
class object_t {
public:
/// constructor
///
/// @param[in] value Value to store in object_t
template <typename T>
object_t(T value)
: self_(std::make_shared<model_t<T>>(std::move(value))) {}
/// draw
///
/// Draw the object
/// @param[in] obj Object to draw
/// @param[in] out Output stream to draw to
/// @param[in] position Spacing from left side
friend void draw(const object_t& obj, std::ostream& out, std::size_t position) {
obj.self_->draw_(out, position);
}
private:
/// concept_t
///
/// Represents a drawable object
struct concept_t {
/// draw
///
/// Draw the object
/// @param[in] out Output stream to draw to
/// @param[in[ position Spacing from left side
virtual void draw_(std::ostream& out, std::size_t position) const = 0;
/// destructor
virtual ~concept_t() = default;
};
/// model_t
///
/// Underlying representation of document objects
template <typename T>
struct model_t final : concept_t {
/// constructor
///
/// @param[in] data Data to hold in the document object
model_t(T data)
: data_(std::move(data)) {}
/// draw
///
/// Draw the underlying object
/// @param[in] out Output stream to draw to
/// @param[in] position Spacing from left side
void draw_(std::ostream& out, std::size_t position) const override {
draw(data_, out, position);
}
/// underlying data
T data_;
};
/// holds abstract representation of the object
std::shared_ptr<const concept_t> self_;
};
using document_t = std::vector<object_t>;
void draw(const document_t& document, std::ostream& out, std::size_t position) {
out << "<document>\n";
for (const auto& e : document)
draw(e, out, position + 2);
std::cout << "</document>\n";
}
struct my_object_t {
// blah
};
void draw(const my_object_t& document, std::ostream& out, std::size_t position) {
out << std::string(position, ' ') << "my_document_t\n";
}
int main() {
document_t document;
document.push_back(0);
document.push_back(1);
document.push_back("Hello, world!");
document.push_back(my_object_t());
draw(document, std::cout, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment