-
Notifications
You must be signed in to change notification settings - Fork 0
/
polymorphism_runtime.cpp
114 lines (95 loc) · 2.01 KB
/
polymorphism_runtime.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
// See Sean Parent's talk "Better Code: Runtime Polymorphism"
// https://www.youtube.com/watch?v=QGcVXgEVMJg
class LogEvent
{
public:
LogEvent() = default;
LogEvent(const LogEvent&) = delete;
LogEvent(LogEvent&&) = default;
template <typename T>
LogEvent(T&& impl)
: m_impl(new model_t<typename std::decay<T>::type>(std::forward<T>(impl)))
{
}
LogEvent& operator=(const LogEvent&) = delete;
LogEvent& operator=(LogEvent&&) = default;
template <typename T>
LogEvent& operator=(T&& impl)
{
m_impl.reset(new model_t<typename std::decay<T>::type>(std::forward<T>(impl)));
return *this;
}
std::string display() const
{
return m_impl->do_display();
}
private:
struct concept_t
{
virtual ~concept_t()
{
}
virtual std::string do_display() const = 0;
};
template <typename T>
struct model_t : public concept_t
{
model_t() = default;
model_t(const T& v)
: m_data(v)
{
}
model_t(T&& v)
: m_data(std::move(v))
{
}
std::string do_display() const override
{
return m_data.display();
}
T m_data;
};
std::unique_ptr<concept_t> m_impl;
};
struct Rectangle
{
int h;
int w;
std::string display() const
{
return "Logged rectangle";
}
};
struct Circle
{
int r;
std::string display() const
{
return "Logged circle";
}
};
struct Sprite
{
std::string path;
std::string display() const
{
return "Logged sprite";
}
};
int main()
{
std::vector<LogEvent> logger;
logger.push_back(Rectangle{12, 42});
logger.push_back(Circle{10});
logger.push_back(Sprite{"monster.png"});
for (const auto& event : logger)
{
std::cout << event.display() << std::endl;
}
}