Skip to content

Instantly share code, notes, and snippets.

@tyhenry
Forked from martinmoene/value-semantics-sean-parent.cpp
Last active November 7, 2020 00:39
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 tyhenry/390b3ffb260c437edb22ebb7c409a47d to your computer and use it in GitHub Desktop.
Save tyhenry/390b3ffb260c437edb22ebb7c409a47d to your computer and use it in GitHub Desktop.
Code from talk: Inheritance Is The Base Class of Evil by Sean Parent at Going Native 2013
// Sean Parent. Inheritance Is The Base Class of Evil. Going Native 2013
// Video: https://www.youtube.com/watch?v=bIhUE5uUFOA
// Code : https://github.com/sean-parent/sean-parent.github.io/wiki/Papers-and-Presentations
/*
Copyright 2013 Adobe Systems Incorporated
Distributed under the MIT License (see license at
http://stlab.adobe.com/licenses.html)
This file is intended as example code and is not production quality.
*/
#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
// using namespace std;
/******************************************************************************/
// Library
template<class V, class C>
inline void visit( V& visitor, C& component ) {
// assert - visit needs define for types <V,C>
std::assert( false, __func__ " is undefined!" );
}
struct Visitor {
template<class T> void visit(T& t){ visit(*this, t) };
};
class Component {
public:
template <class T>
Component(T x) : m_self( new Model<T>(std::move(x)) ) {}
// void accept(Visitor& visit) {
// x.self_->draw_(out, pos);
// }
private:
struct Concept {
virtual ~Concept() = default;
virtual void accept(Visitor&) = 0;
};
template <typename T>
struct Model : Concept {
Model(T x) : value (move(x)) { } // move c'tor
void accept(Visitor& visitor) override { visit( visitor, value ); }
T value;
};
std::shared_ptr<const Concept> m_self;
};
using document_t = vector<object_t>;
void draw(const document_t& x, ostream& out, size_t position)
{
out << string(position, ' ') << "<document>" << endl;
for (auto& e : x) draw(e, out, position + 2);
out << string(position, ' ') << "</document>" << endl;
}
using history_t = vector<document_t>;
void commit(history_t& x)
{
assert(x.size());
x.push_back(x.back());
}
void undo(history_t& x)
{
assert(x.size());
x.pop_back();
}
document_t& current(history_t& x)
{
assert(x.size());
return x.back();
}
/******************************************************************************/
// Client
class my_class_t
{
/* ... */
};
void draw(const my_class_t&, ostream& out, size_t position)
{
out << string(position, ' ') << "my_class_t" << endl;
}
int main()
{
history_t h(1);
current(h).emplace_back(0);
current(h).emplace_back(string("Hello!"));
draw(current(h), cout, 0);
cout << "--------------------------" << endl;
commit(h);
current(h).emplace_back(current(h));
current(h).emplace_back(my_class_t());
current(h)[1] = string("World");
draw(current(h), cout, 0);
cout << "--------------------------" << endl;
undo(h);
draw(current(h), cout, 0);
}
#if 0
g++ -std=c++11 -o value-semantics-unique.exe value-semantics-unique.cpp && value-semantics-unique.exe
<document>
0
Hello!
</document>
--------------------------
<document>
0
World
<document>
0
Hello!
</document>
my_class_t
</document>
--------------------------
<document>
0
Hello!
</document>
#endif
// Sean Parent. Inheritance Is The Base Class of Evil. Going Native 2013
// Video: https://www.youtube.com/watch?v=bIhUE5uUFOA
// Code : https://github.com/sean-parent/sean-parent.github.io/wiki/Papers-and-Presentations
/*
Copyright 2013 Adobe Systems Incorporated
Distributed under the MIT License (see license at
http://stlab.adobe.com/licenses.html)
This file is intended as example code and is not production quality.
*/
#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;
/******************************************************************************/
// Library
template <typename T>
void draw(const T& x, ostream& out, size_t position)
{
out << string(position, ' ') << x << endl;
}
class object_t
{
public:
template <typename T>
object_t(T x) : self_(new model<T>(move(x)))
{ }
// object_t(const object_t& x) : self_(x.self_->copy_())
// { }
//
// object_t(object_t&&) noexcept = default;
//
// object_t& operator=(const object_t& x)
// {
// object_t tmp(x);
// *this = move(tmp);
// return *this;
// }
//
// object_t& operator=(object_t&&) noexcept = default;
friend void draw(const object_t& x, ostream& out, size_t position)
{
x.self_->draw_(out, position);
}
private:
struct concept_t
{
virtual ~concept_t() = default;
// virtual concept_t* copy_() const = 0;
virtual void draw_(ostream&, size_t) const = 0;
};
template <typename T>
struct model : concept_t
{
model(T x) : data_(move(x)) { }
// concept_t* copy_() const
// {
// return new model(*this);
// }
void draw_(ostream& out, size_t position) const
{
draw(data_, out, position);
}
T data_;
};
shared_ptr<const concept_t> self_;
// unique_ptr<const concept_t> self_;
};
using document_t = vector<object_t>;
void draw(const document_t& x, ostream& out, size_t position)
{
out << string(position, ' ') << "<document>" << endl;
for (auto& e : x) draw(e, out, position + 2);
out << string(position, ' ') << "</document>" << endl;
}
using history_t = vector<document_t>;
void commit(history_t& x)
{
assert(x.size());
x.push_back(x.back());
}
void undo(history_t& x)
{
assert(x.size());
x.pop_back();
}
document_t& current(history_t& x)
{
assert(x.size());
return x.back();
}
/******************************************************************************/
// Client
class my_class_t
{
/* ... */
};
void draw(const my_class_t&, ostream& out, size_t position)
{
out << string(position, ' ') << "my_class_t" << endl;
}
int main()
{
history_t h(1);
current(h).emplace_back(0);
current(h).emplace_back(string("Hello!"));
draw(current(h), cout, 0);
cout << "--------------------------" << endl;
commit(h);
current(h).emplace_back(current(h));
current(h).emplace_back(my_class_t());
current(h)[1] = string("World");
draw(current(h), cout, 0);
cout << "--------------------------" << endl;
undo(h);
draw(current(h), cout, 0);
}
#if 0
g++ -std=c++11 -o value-semantics-unique.exe value-semantics-unique.cpp && value-semantics-unique.exe
<document>
0
Hello!
</document>
--------------------------
<document>
0
World
<document>
0
Hello!
</document>
my_class_t
</document>
--------------------------
<document>
0
Hello!
</document>
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment