#pragma once #include #include #include #include #include #include #include #include class bad_cast : public std::exception { std::string why; public: bad_cast( const std::type_index& f, const std::type_index& t ) : std::exception() { why = std::string{"bad cast of "} + f.name() + " to " + t.name(); } ~bad_cast() override = default; const char* what() const noexcept override { return why.c_str(); } }; template std::type_index class_of() { return { typeid(T) }; } template using ptr = std::unique_ptr; struct object { std::type_index get_class() const { return { this ? typeid(*this) : typeid(std::nullptr_t) }; } template T& as() { T* p = dynamic_cast(this); if ( !p ) throw bad_cast{ get_class(), class_of() }; return *p; } template const T& as() const { const T* p = dynamic_cast(this); if ( !p ) throw bad_cast{ get_class(), class_of() }; return *p; } virtual ptr new_inst() const = 0; virtual ptr new_copy() const = 0; virtual object& operator= (const object&) = 0; virtual ~object() = default; }; template static inline ptr make(Args&&... args) { return std::make_unique(std::forward(args)...); } template ptr as_ptr( ptr&& p ) { return ptr{ &p.release()->template as() }; } struct ordered : public virtual object { virtual int cmp(const ordered&) const = 0; bool operator< (const ordered& that) const { return cmp(that) < 0; } bool operator<= ( const ordered& that ) const { return cmp(that) <= 0; } bool operator== ( const ordered& that ) const { return cmp(that) == 0; } bool operator!= ( const ordered& that ) const { return cmp(that) != 0; } bool operator> ( const ordered& that ) const { return cmp(that) > 0; } bool operator>= ( const ordered& that ) const { return cmp(that) >= 0; } }; struct printable : public virtual object { virtual void print(std::ostream&) const = 0; }; class character : public ordered, public printable { char x; public: character() = default; character(char x) : x(x) {} character(const character&) = default; character(character&&) = default; ptr new_inst() const override { return make(); } ptr new_copy() const override { return make(*this); } character& operator= (const character& that) { x = that.x; return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ character& operator= (character&&) = default; ~character() override = default; int cmp(const character& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; } int cmp(const ordered& that) const override { return cmp( that.as() ); } /***/ void print(std::ostream& out) const override { if ( 0x20 <= x && x <= 0x7E ) { out << "'" << x << "'"; } else { out << "'\\" << std::hex << (unsigned int)x << std::setbase(0) << "'"; } } }; class short_integer : public ordered, public printable { short x; public: short_integer() = default; short_integer(short x) : x(x) {} short_integer(const short_integer&) = default; short_integer(short_integer&&) = default; ptr new_inst() const override { return make(); } ptr new_copy() const override { return make(*this); } short_integer& operator= (const short_integer& that) { x = that.x; return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ short_integer& operator= (short_integer&&) = default; ~short_integer() override = default; int cmp(const short_integer& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; } int cmp(const ordered& that) const override { return cmp( that.as() ); } /***/ void print(std::ostream& out) const override { out << x; } }; class integer : public ordered, public printable { int x; public: integer() = default; integer(int x) : x(x) {} integer(const integer&) = default; integer(integer&&) = default; ptr new_inst() const override { return make(); } ptr new_copy() const override { return make(*this); } integer& operator= (const integer& that) { x = that.x; return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ integer& operator= (integer&&) = default; ~integer() override = default; int cmp(const integer& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; } int cmp(const ordered& that) const override { return cmp( that.as() ); } /***/ void print(std::ostream& out) const override { out << x; } }; class pair : public ordered, public printable { ptr x; ptr y; public: pair() = default; pair(ptr&& x, ptr&& y) : x(std::move(x)), y(std::move(y)) {} pair(const pair& that) : x(that.x->new_copy()), y(that.y->new_copy()) {} pair(pair&& that) : x(std::move(that.x)), y(std::move(that.y)) {} ptr new_inst() const override { return make(); } ptr new_copy() const override { return make(x->new_copy(), y->new_copy()); } pair& operator= (const pair& that) { x = that.x->new_copy(); y = that.y->new_copy(); return *this; } object& operator= (const object& that) override { return *this = that.as(); } /***/ pair& operator= (pair&& that) { x = std::move(that.x); y = std::move(that.y); return *this; } ~pair() override = default; int cmp(const pair& that) const { int c = x->as().cmp( that.x->as() ); /***/ if ( c != 0 ) return c; return y->as().cmp( that.y->as() ); /***/ } int cmp(const ordered& that) const override { return cmp( that.as() ); } /***/ void print(std::ostream& out) const override { out << "["; x->as().print(out); /***/ out << ", "; y->as().print(out); /***/ out << "]"; } };