source: doc/papers/OOPSLA17/evaluation/object.hpp@ 180f249

ADT ast-experimental enum forall-pointer-decay pthread-emulation qualifiedEnum
Last change on this file since 180f249 was f4e3419d, checked in by Peter A. Buhr <pabuhr@…>, 8 years ago

restructure paper documents

  • Property mode set to 100644
File size: 6.5 KB
Line 
1#pragma once
2#include <cstddef>
3#include <exception>
4#include <iomanip>
5#include <memory>
6#include <ostream>
7#include <string>
8#include <typeinfo>
9#include <typeindex>
10
11class bad_cast : public std::exception {
12 std::string why;
13public:
14 bad_cast( const std::type_index& f, const std::type_index& t ) : std::exception() {
15 why = std::string{"bad cast of "} + f.name() + " to " + t.name();
16 }
17 ~bad_cast() override = default;
18
19 const char* what() const noexcept override { return why.c_str(); }
20};
21
22template<typename T> std::type_index class_of() { return { typeid(T) }; }
23
24template<typename T> using ptr = std::unique_ptr<T>;
25
26struct object {
27 std::type_index get_class() const { return { this ? typeid(*this) : typeid(std::nullptr_t) }; }
28
29 template<typename T> T& as() {
30 T* p = dynamic_cast<T*>(this);
31 if ( !p ) throw bad_cast{ get_class(), class_of<T>() };
32 return *p;
33 }
34
35 template<typename T> const T& as() const {
36 const T* p = dynamic_cast<const T*>(this);
37 if ( !p ) throw bad_cast{ get_class(), class_of<T>() };
38 return *p;
39 }
40
41 virtual ptr<object> new_inst() const = 0;
42 virtual ptr<object> new_copy() const = 0;
43 virtual object& operator= (const object&) = 0;
44 virtual ~object() = default;
45};
46
47template<typename T, typename... Args> static inline ptr<T> make(Args&&... args) {
48 return std::make_unique<T>(std::forward<Args>(args)...);
49}
50
51template<typename To, typename From>
52ptr<To> as_ptr( ptr<From>&& p ) { return ptr<To>{ &p.release()->template as<To>() }; }
53
54struct ordered : public virtual object {
55 virtual int cmp(const ordered&) const = 0;
56
57 bool operator< (const ordered& that) const { return cmp(that) < 0; }
58 bool operator<= ( const ordered& that ) const { return cmp(that) <= 0; }
59 bool operator== ( const ordered& that ) const { return cmp(that) == 0; }
60 bool operator!= ( const ordered& that ) const { return cmp(that) != 0; }
61 bool operator> ( const ordered& that ) const { return cmp(that) > 0; }
62 bool operator>= ( const ordered& that ) const { return cmp(that) >= 0; }
63};
64
65struct printable : public virtual object {
66 virtual void print(std::ostream&) const = 0;
67};
68
69class boolean : public ordered, public printable {
70 bool x;
71public:
72 boolean() = default;
73 boolean(bool x) : x(x) {}
74 boolean(const boolean&) = default;
75 boolean(boolean&&) = default;
76 ptr<object> new_inst() const override { return make<boolean>(); }
77 ptr<object> new_copy() const override { return make<boolean>(*this); }
78 boolean& operator= (const boolean& that) {
79 x = that.x;
80 return *this;
81 }
82 object& operator= (const object& that) override { return *this = that.as<boolean>(); } /***/
83 boolean& operator= (boolean&&) = default;
84 ~boolean() override = default;
85
86 int cmp(const boolean& that) const { return x == that.x ? 0 : x == false ? -1 : 1; }
87 int cmp(const ordered& that) const override { return cmp( that.as<boolean>() ); } /***/
88
89 void print(std::ostream& out) const override { out << (x ? "true" : "false"); }
90};
91
92class character : public ordered, public printable {
93 char x;
94public:
95 character() = default;
96 character(char x) : x(x) {}
97 character(const character&) = default;
98 character(character&&) = default;
99 ptr<object> new_inst() const override { return make<character>(); }
100 ptr<object> new_copy() const override { return make<character>(*this); }
101 character& operator= (const character& that) {
102 x = that.x;
103 return *this;
104 }
105 object& operator= (const object& that) override { return *this = that.as<character>(); } /***/
106 character& operator= (character&&) = default;
107 ~character() override = default;
108
109 int cmp(const character& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; }
110 int cmp(const ordered& that) const override { return cmp( that.as<character>() ); } /***/
111
112 void print(std::ostream& out) const override {
113 if ( 0x20 <= x && x <= 0x7E ) { out << "'" << x << "'"; }
114 else { out << "'\\" << std::hex << (unsigned int)x << std::setbase(0) << "'"; }
115 }
116};
117
118class integer : public ordered, public printable {
119 int x;
120public:
121 integer() = default;
122 integer(int x) : x(x) {}
123 integer(const integer&) = default;
124 integer(integer&&) = default;
125 ptr<object> new_inst() const override { return make<integer>(); }
126 ptr<object> new_copy() const override { return make<integer>(*this); }
127 integer& operator= (const integer& that) {
128 x = that.x;
129 return *this;
130 }
131 object& operator= (const object& that) override { return *this = that.as<integer>(); } /***/
132 integer& operator= (integer&&) = default;
133 ~integer() override = default;
134
135 int cmp(const integer& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; }
136 int cmp(const ordered& that) const override { return cmp( that.as<integer>() ); } /***/
137
138 void print(std::ostream& out) const override { out << x; }
139};
140
141class c_string : public printable {
142 static constexpr const char* empty = "";
143 const char* s;
144public:
145 c_string() : s(empty) {}
146 c_string(const char* s) : s(s) {}
147 c_string(const c_string&) = default;
148 c_string(c_string&&) = default;
149 ptr<object> new_inst() const override { return make<c_string>(); }
150 ptr<object> new_copy() const override { return make<c_string>(s); }
151 c_string& operator= (const c_string& that) {
152 s = that.s;
153 return *this;
154 }
155 object& operator= (const object& that) override { return *this = that.as<c_string>(); } /***/
156 c_string& operator= (c_string&&) = default;
157 ~c_string() override = default;
158
159 void print(std::ostream& out) const override { out << s; }
160};
161
162class pair : public ordered, public printable {
163 ptr<object> x;
164 ptr<object> y;
165public:
166 pair() = default;
167 pair(ptr<object>&& x, ptr<object>&& y) : x(std::move(x)), y(std::move(y)) {}
168 pair(const pair& that) : x(that.x->new_copy()), y(that.y->new_copy()) {}
169 pair(pair&& that) : x(std::move(that.x)), y(std::move(that.y)) {}
170 ptr<object> new_inst() const override { return make<pair>(); }
171 ptr<object> new_copy() const override { return make<pair>(x->new_copy(), y->new_copy()); }
172 pair& operator= (const pair& that) {
173 x = that.x->new_copy();
174 y = that.y->new_copy();
175 return *this;
176 }
177 object& operator= (const object& that) override { return *this = that.as<pair>(); } /***/
178 pair& operator= (pair&& that) {
179 x = std::move(that.x);
180 y = std::move(that.y);
181 return *this;
182 }
183 ~pair() override = default;
184
185 int cmp(const pair& that) const {
186 int c = x->as<ordered>().cmp( that.x->as<ordered>() ); /***/
187 if ( c != 0 ) return c;
188 return y->as<ordered>().cmp( that.y->as<ordered>() ); /***/
189 }
190 int cmp(const ordered& that) const override { return cmp( that.as<pair>() ); }
191
192 void print(std::ostream& out) const override {
193 out << "[";
194 x->as<printable>().print(out); /***/
195 out << ", ";
196 y->as<printable>().print(out); /***/
197 out << "]";
198 }
199};
Note: See TracBrowser for help on using the repository browser.