// ************************************************************************ // ****** ****** // ****** header file Class.h ****** // ****** ****** // ************************************************************************ // Copyright (c) 2000 Jaroslav Kroupa // Permission to use, copy, modify, distribute is hereby granted without // fee, provided that the above copyright notice and this permission // notice appear in all copies. #ifndef __CLASS_H #define __CLASS_H //========================================================================= // ISO C++ #include #include #include #include //========================================================================= // Jmena definovana v namespace ClassImpl jsou urcena pouze pro implementaci // predavani trid a nemela by se pouzivat jinde namespace ClassImpl { class ClassObject; } // namespace ClassImpl class BasicObjectHolder; class ConstBasicObjectHolder; //========================================================================= // class Class //========================================================================= class Class { public: struct XError : std::runtime_error { XError(const char* msg): std::runtime_error(msg) {} }; struct XNullObject : XError { XNullObject(): XError("Null object used") {} }; struct XNullClass : XError { XNullClass(): XError("Null class used") {} }; struct XInvalidOperation : XError { XInvalidOperation(): XError("Invalid operation called") {} }; public: Class() throw(): classPtr(NULL) {} Class(const ClassImpl::ClassObject* cls) throw(): classPtr(cls) {} public: inline const char* TypeName() const throw(XNullClass); inline BasicObjectHolder NewObject() const; public: operator const ClassImpl::ClassObject*() const throw() { return classPtr; } bool operator!() const throw() { return !classPtr; } bool operator==(Class cls) const throw() { return classPtr==cls.classPtr; } bool operator!=(Class cls) const throw() { return classPtr!=cls.classPtr; } private: const ClassImpl::ClassObject* GetClassPtr() const throw(XNullClass) { if (!classPtr) throw XNullClass(); return classPtr; } private: const ClassImpl::ClassObject* classPtr; }; // class Class //========================================================================= namespace ClassImpl { //========================================================================= // Jmena definovana v namespace ClassImpl jsou urcena pouze pro implementaci // predavani trid a nemela by se pouzivat jinde class Object { protected: virtual ~Object() {} public: unsigned long AddRef() const throw() { assert(this); return ++refCount; } unsigned long Release() const throw() { assert(this); assert(refCount>0); if (--refCount==0) { delete this; return 0; } return refCount; } public: inline Class GetClass() const throw(); inline BasicObjectHolder Clone() const; inline bool Equal(const Object* o) const throw(); inline std::ostream& Print(std::ostream& out) const; inline const void* ObjectAdress() const throw(); inline size_t ObjectSize() const throw(); protected: // "strange" names used to avoid possible conflicts virtual Class _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_get_class() const throw()=0; virtual Object* _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_clone() const=0; virtual bool _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_equal(const Object* o,bool tryInv) const throw()=0; virtual std::ostream& _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_print(std::ostream& out) const=0; virtual const void* _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_object_address() const throw()=0; virtual size_t _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_object_size() const throw()=0; private: mutable unsigned long refCount; }; // class Object //------------------------------------------------------------------------- template class AConstPtrClassBase { public: typedef T value_type; typedef const T* pointer; typedef const T& reference; public: AConstPtrClassBase() throw(): ptr(NULL) {} AConstPtrClassBase(const T* p) throw(): ptr(p) {} public: operator const T*() const throw() { return ptr; } const T& operator*() const throw() { assert(ptr); return *ptr; } const T* operator->() const throw() { assert(ptr); return GetPtr(); } const T* GetPtr() const throw() { return ptr; } bool operator!() const throw() { return !ptr; } protected: const T* ptr; private: AConstPtrClassBase(const AConstPtrClassBase&); AConstPtrClassBase& operator=(const AConstPtrClassBase&); }; // class AConstPtrClassBase //------------------------------------------------------------------------- template class APtrClassBase { public: typedef T value_type; typedef T* pointer; typedef T& reference; public: APtrClassBase() throw(): ptr(NULL) {} APtrClassBase(T* p) throw(): ptr(p) {} public: operator T*() const throw() { return ptr; } T& operator*() const throw() { assert(ptr); return *ptr; } T* operator->() const throw() { assert(ptr); return GetPtr(); } T* GetPtr() const throw() { return ptr; } bool operator!() const throw() { return !ptr; } protected: T* ptr; private: APtrClassBase(const APtrClassBase&); APtrClassBase& operator=(const APtrClassBase&); }; // class APtrClassBase //------------------------------------------------------------------------- class ClassObject { friend class Class; protected: virtual const char* type_name() const throw()=0; virtual Object* create_new_object() const=0; }; // class ClassObject //========================================================================= } // namespace ClassImpl //========================================================================= //========================================================================= // class BasicObjectHolder //========================================================================= class BasicObjectHolder : public ClassImpl::APtrClassBase { typedef ClassImpl::APtrClassBase inherited; public: BasicObjectHolder() throw() {} BasicObjectHolder(ClassImpl::Object* po) throw() { SetPtr(po); } BasicObjectHolder(const BasicObjectHolder& oh) throw() { SetPtr(oh.ptr); } ~BasicObjectHolder() throw() { ReleasePtr(); } BasicObjectHolder& operator=(ClassImpl::Object* po) throw() { SetPtr(po); return *this; } BasicObjectHolder& operator=(const BasicObjectHolder& oh) throw() { SetPtr(oh.ptr); return *this; } public: template static BasicObjectHolder FromPtr(T* ptr) { return BasicObjectHolder(&dynamic_cast(*ptr)); } public: void SetPtr(ClassImpl::Object* po) throw() { if (po) po->AddRef(); ReleasePtr(); ptr=po; } void ReleasePtr() throw() { if (ptr) ptr->Release(); ptr=NULL; } public: Class GetClass() const throw() { return GetObjectPtr()->GetClass(); } const char* TypeName() const throw(Class::XNullClass) { return GetObjectPtr()->GetClass().TypeName(); } BasicObjectHolder Clone() const { return GetObjectPtr()->Clone(); } bool Equal(const BasicObjectHolder& o) const { return ptr ? ptr->Equal(o.GetPtr()) : !o; } inline bool Equal(const ConstBasicObjectHolder& o) const; std::ostream& Print(std::ostream& out) const { return ptr ? ptr->Print(out) : out<<"NULL@0"; } private: ClassImpl::Object* GetObjectPtr() const { if (!ptr) throw Class::XNullObject(); return ptr;} }; // class BasicObjectHolder inline std::ostream& operator<<(std::ostream& out,const BasicObjectHolder& objPtr) { return objPtr.Print(out); } //========================================================================= // class ConstBasicObjectHolder //========================================================================= class ConstBasicObjectHolder : public ClassImpl::AConstPtrClassBase { typedef ClassImpl::AConstPtrClassBase inherited; public: ConstBasicObjectHolder() throw() {} ConstBasicObjectHolder(const ClassImpl::Object* po) throw() { SetPtr(po); } ConstBasicObjectHolder(const ConstBasicObjectHolder& oh) throw() { SetPtr(oh.ptr); } ConstBasicObjectHolder(const BasicObjectHolder& oh) throw() { SetPtr(oh.GetPtr()); } ~ConstBasicObjectHolder() throw() { ReleasePtr(); } ConstBasicObjectHolder& operator=(const ClassImpl::Object* po) throw() { SetPtr(po); return *this; } ConstBasicObjectHolder& operator=(const ConstBasicObjectHolder& oh) throw() { SetPtr(oh.ptr); return *this; } ConstBasicObjectHolder& operator=(const BasicObjectHolder& oh) throw() { SetPtr(oh.GetPtr()); return *this; } public: template static ConstBasicObjectHolder FromPtr(const T* ptr) { return ConstBasicObjectHolder(&dynamic_cast(*ptr)); } public: void SetPtr(const ClassImpl::Object* po) throw() { if (po) po->AddRef(); ReleasePtr(); ptr=po; } void ReleasePtr() throw() { if (ptr) ptr->Release(); ptr=NULL; } public: Class GetClass() const throw() { return GetObjectPtr()->GetClass(); } const char* TypeName() const throw(Class::XNullClass) { return GetObjectPtr()->GetClass().TypeName(); } BasicObjectHolder Clone() const { return GetObjectPtr()->Clone(); } bool Equal(const BasicObjectHolder& o) const { return ptr ? ptr->Equal(o.GetPtr()) : !o; } bool Equal(const ConstBasicObjectHolder& o) const { return ptr ? ptr->Equal(o.GetPtr()) : !o; } std::ostream& Print(std::ostream& out) const { return ptr ? ptr->Print(out) : out<<"NULL@0"; } private: const ClassImpl::Object* GetObjectPtr() const { if (!ptr) throw Class::XNullObject(); return ptr;} }; // class ConstBasicObjectHolder inline std::ostream& operator<<(std::ostream& out,const ConstBasicObjectHolder& objPtr) { return objPtr.Print(out); } //------------------------------------------------------------------------- inline bool BasicObjectHolder::Equal(const ConstBasicObjectHolder& o) const { return ptr ? ptr->Equal(o.GetPtr()) : !o; } //========================================================================= inline const char* Class::TypeName() const throw(XNullClass) { return GetClassPtr()->type_name(); } inline BasicObjectHolder Class::NewObject() const { return GetClassPtr()->create_new_object(); } //========================================================================= namespace ClassImpl { //========================================================================= // Jmena definovana v namespace ClassImpl jsou urcene pouze pro implementaci // predavani trid a nemely by se pouzivat jinde inline Class Object::GetClass() const throw() { return _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_get_class(); } inline BasicObjectHolder Object::Clone() const { return _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_clone(); } inline bool Object::Equal(const Object* o) const throw() { return o ? _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_equal(o,true) : false; } inline std::ostream& Object::Print(std::ostream& out) const { return _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_print(out); } inline const void* Object::ObjectAdress() const throw() { return _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_object_address(); } inline size_t Object::ObjectSize() const throw() { return _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_object_size(); } //------------------------------------------------------------------------- struct PtrToObject { PtrToObject(const Object& p): ptr(&p) {} const Object* ptr; }; // struct PtrToObject inline std::ostream& operator<<(std::ostream& out,PtrToObject p) { return p.ptr ? out<GetClass().TypeName()<<"@"<ObjectAdress() : out<<"NULL@0"; } //------------------------------------------------------------------------- template struct Comparable : public Type { struct ComparablePtr { ComparablePtr(const Comparable& c): ptr(&c) {} const Comparable* ptr; }; struct TypePtr { TypePtr(const Type& t): ptr(&t) {} const Type* ptr; }; friend bool operator==(ComparablePtr tp1,TypePtr tp2) { const char* adr1=reinterpret_cast(static_cast(tp1.ptr)); const char* adr2=reinterpret_cast(tp2.ptr); return std::equal(adr1,adr1+sizeof(Type),adr2); } }; //------------------------------------------------------------------------- template struct ObjectDerived : public Comparable, public Object { ObjectDerived() {} ~ObjectDerived() throw() {} bool _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_equal(const Object* o,bool tryInv) const throw() { const Type* t=dynamic_cast(o); if (t) return *this==*t; if (tryInv) return _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_equal(this,false); return false; } std::ostream& _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_print(std::ostream& out) const { return out<<*this; } const void* _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_object_address() const throw() { return static_cast(this); } size_t _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_object_size() const throw() { return sizeof(Type); } }; // class ObjectDerived //========================================================================= } // namespace ClassImpl //========================================================================= //========================================================================= // class ClassOf //========================================================================= template class ClassOf { public: static const char* TypeName() throw() { return typeid(Type).name(); } static BasicObjectHolder NewObject() { return GetClassObject().NewObject(); } operator Class() const throw() { return GetClassObject(); } public: static Class GetClassObject() throw() { static ClassObjectImpl clsObject; static Class cls(&clsObject); return cls; } public: struct ObjectDerived : public ClassImpl::ObjectDerived { Class _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_get_class() const throw() { return GetClassObject(); } ClassImpl::Object* _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_clone() const { return new ObjectDerived(*this); } }; // class ObjectDerived struct ClassObjectImpl : public ClassImpl::ClassObject { const char* type_name() const throw() { return typeid(Type).name(); } ClassImpl::Object* create_new_object() const { return new ObjectDerived; } }; // class AClassObjectImpl }; // class ClassOf //========================================================================= // class NonCopiableClassOf //========================================================================= template class NonCopiableClassOf { public: static const char* TypeName() throw() { return typeid(Type).name(); } static BasicObjectHolder NewObject() { return GetClassObject().NewObject(); } operator Class() const throw() { return GetClassObject(); } public: static Class GetClassObject() throw() { static ClassObjectImpl clsObject; static Class cls(&clsObject); return cls; } public: struct ObjectDerived : public ClassImpl::ObjectDerived { Class _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_get_class() const throw() { return GetClassObject(); } ClassImpl::Object* _7D57C6E0_887B_11d4_A3CF_0000C0555BC8_clone() const { throw Class::XInvalidOperation(); } }; // class ObjectDerived struct ClassObjectImpl : public ClassImpl::ClassObject { const char* type_name() const throw() { return typeid(Type).name(); } ClassImpl::Object* create_new_object() const { return new ObjectDerived; } }; // class AClassObjectImpl }; // class NonCopiableClassOf //========================================================================= // class ClassDerivedFrom //========================================================================= // syntakticka kontrola: // typedef Type* pointer; // Base* p=pointer(); zakaze prevod (NonCopiable)ClassOf // na ClassDerivedFrom pokud Type neni odvozeno z Base template class ClassDerivedFrom { public: ClassDerivedFrom() {} template ClassDerivedFrom(const ClassOf& clsOf) { typedef Type* pointer; Base* p=pointer(); cls=clsOf; } template ClassDerivedFrom(const NonCopiableClassOf& clsOf) { typedef Type* pointer; Base* p=pointer(); cls=clsOf; } template ClassDerivedFrom& operator=(const ClassOf& clsOf) { typedef Type* pointer; Base* p=pointer(); cls=clsOf; return *this; } template ClassDerivedFrom& operator=(const NonCopiableClassOf& clsOf) { typedef Type* pointer; Base* p=pointer(); cls=clsOf; return *this; } public: const char* TypeName() const throw(Class::XNullClass) { return cls.TypeName(); } BasicObjectHolder NewObject() const { return cls.NewObject(); } operator Class() const throw() { return cls; } public: operator const ClassImpl::ClassObject*() const throw() { return cls; } bool operator!() const throw() { return !cls; } bool operator==(ClassDerivedFrom c) const throw() { return cls==c.cls; } bool operator!=(ClassDerivedFrom c) const throw() { return cls!=c.cls; } public: // dynamic type check, throws exception if c is not valid Class void Assign(Class c) throw(std::bad_cast,Class::XNullClass) { if (c) dynamic_cast(*c.NewObject()); cls=c; } private: Class cls; }; // class ClassDerivedFrom //========================================================================= // class ObjectHolder //========================================================================= // syntakticka kontrola: // typedef T2* P2; // Type* p=P2(); zakaze prevod ObjectHolder na ObjectHolder // pokud T2 neni odvozeno z Type // static_cast(P2()); zakaze prevod ObjectHolder na // ObjectHolder pokud T2 neni odvozeno z Type nebo naopak template class ObjectHolder : public ClassImpl::APtrClassBase { public: ObjectHolder() throw() {} ObjectHolder(const BasicObjectHolder& o) throw(std::bad_cast) { SetObject(o); } template ObjectHolder(const ObjectHolder& oh) throw(std::bad_cast) { typedef T2* P2; static_cast(P2()); SetObject(oh); } ObjectHolder& operator=(const BasicObjectHolder& o) throw(std::bad_cast) { SetObject(o); return *this; } template ObjectHolder& operator=(const ObjectHolder& oh) throw(std::bad_cast) { typedef T2* P2; static_cast(P2()); SetObject(oh); return *this; } operator BasicObjectHolder() const { return object; } public: void SetObject(const BasicObjectHolder& o) throw(std::bad_cast) { ptr=(object=o) ? &dynamic_cast(*object) : NULL; } void ReleaseObject() throw() { object.ReleasePtr(); ptr=NULL; } public: Class GetClass() const throw() { return object.GetClass(); } ObjectHolder Clone() const { return object.Clone(); } bool Equal(const BasicObjectHolder& o) const { return object.Equal(o); } bool Equal(const ConstBasicObjectHolder& o) const { return object.Equal(o); } std::ostream& Print(std::ostream& out) const { return object.Print(out); } protected: BasicObjectHolder object; }; // class ObjectHolder template inline std::ostream& operator<<(std::ostream& out,const ObjectHolder& objPtr) { return objPtr.Print(out); } //========================================================================= // class ConstObjectHolder //========================================================================= // syntakticka kontrola: // typedef (const) T2* P2; // Type* p=P2(); zakaze prevod (Const)ObjectHolder na // ConstObjectHolder pokud T2 neni odvozeno z Type // static_cast(P2()); zakaze prevod (Const)ObjectHolder // na ConstObjectHolder pokud T2 neni odvozeno z Type nebo naopak template class ConstObjectHolder : public ClassImpl::AConstPtrClassBase { public: ConstObjectHolder() throw() {} ConstObjectHolder(const ConstBasicObjectHolder& o) throw(std::bad_cast) { SetObject(o); } ConstObjectHolder(const BasicObjectHolder& o) throw(std::bad_cast) { SetObject(o); } template ConstObjectHolder(const ConstObjectHolder& oh) throw(std::bad_cast) { typedef const T2* P2; static_cast(P2()); SetObject(oh); } template ConstObjectHolder(const ObjectHolder& oh) throw(std::bad_cast) { typedef T2* P2; static_cast(P2()); SetObject(oh); } ConstObjectHolder& operator=(const BasicObjectHolder& o) throw(std::bad_cast) { SetObject(o); return *this; } ConstObjectHolder& operator=(const ConstBasicObjectHolder& o) throw(std::bad_cast) { SetObject(o); return *this; } template ConstObjectHolder& operator=(const ConstObjectHolder& oh) throw(std::bad_cast) { typedef const T2* P2; static_cast(P2()); SetObject(oh); return *this; } template ConstObjectHolder& operator=(const ObjectHolder& oh) throw(std::bad_cast) { typedef T2* P2; static_cast(P2()); SetObject(oh); return *this; } operator ConstBasicObjectHolder() const { return object; } public: void SetObject(const ConstBasicObjectHolder& o) throw(std::bad_cast) { ptr=(object=o) ? &dynamic_cast(*object) : NULL; } void ReleaseObject() throw() { object.ReleasePtr(); ptr=NULL; } public: Class GetClass() const throw() { return object.GetClass(); } ObjectHolder Clone() const { return object.Clone(); } bool Equal(const BasicObjectHolder& o) const { return object.Equal(o); } bool Equal(const ConstBasicObjectHolder& o) const { return object.Equal(o); } std::ostream& Print(std::ostream& out) const { return object.Print(out); } protected: ConstBasicObjectHolder object; }; // class ConstObjectHolder template inline std::ostream& operator<<(std::ostream& out,const ConstObjectHolder& objPtr) { return objPtr.Print(out); } //========================================================================= #endif // __CLASS_H