Last active
September 18, 2019 00:45
-
-
Save 2bdkid/45663cbf281405b4e0fc0980dfe8a126 to your computer and use it in GitHub Desktop.
spooky runtime polymorphism
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> | |
#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