#pragma once #include #include #include #include template struct vref; struct concept; template struct value; struct ref { ref(concept *p) : ptr(p) { if (p == 0) throw std::logic_error("null reference"); } ref(ref const &) = default; concept* operator->() { return ptr; } bool operator==(ref const & that) const { return this->ptr == that.ptr; } bool operator<(ref const &) const { throw std::logic_error("ref has redefined syntax sugar: do not use in containers"); } // for helpers ref(std::string const &); ref(char const * str) : ref(std::string(str)) { } ref(bool b) : ref(b ? "true" : "false") { } ref() : ref("nothing") { } value & name() const; operator const char *() const; ref operator=(ref other); // helper constructs new concept with this as link ref operator[](ref links); // helper sets all links from passed concept bool isa(ref what) const; bool isan(ref what) const; concept * ptr; }; template struct vref { vref(value *p) : ptr(p) { } value* operator->() { return ptr; } operator T const &() const { return *ptr; } vref(ref const & other) : ptr(static_cast*>(other.ptr)) { } operator ref() { return ptr; } // for use by containers //bool operator<(ref const & other) const { return ptr < other.ptr; } value * ptr; }; struct concept { // a concept is made of concept-typed links to other concepts std::multimap links; using array = std::vector; ref id(); bool linked(ref type); bool linked(ref type, ref target); ref get(ref type); // returns first template vref vget(ref type) { return get(type); } array getAll(ref type); void link(ref type, ref target); void unlink(ref type, ref target); }; template struct value : public concept, public T { value(T const & val) : T(val) {} value(value const & val) = default; static value& of(ref c) { return *static_cast*>(c.ptr); } };