diff --git a/include/common.h b/include/common.h index 8524162..e789374 100644 --- a/include/common.h +++ b/include/common.h @@ -18,6 +18,94 @@ EXPORT std::ostream& COUT(debug_level dl); typedef std::set UsedType; +class EXPORT ObjectBase; + +// Template for checking and using ObjectBase derivative classes +// Checking if arg is pointer on Derived: if(OBType(arg)) +// Using const ObjectBase* arg as const Derived*: OBType(arg)->SomeCall() +template +class OBType +{ + const O* p; + public: + OBType() = delete; + OBType(OBType&&) = delete; + OBType(OBType&) = delete; + OBType(const ObjectBase* arg) {if(typeid(*arg)==typeid(O)) p=dynamic_cast(arg); else p=0;} + const O* operator->() const {return p;} + operator bool() const {return 0!=p;} +}; + + +// Template for checking and using several ObjectBase derivative classes +// Func is template of class-function template argument of which can be any of Derived classes. +// It must have at least one argument - pointer to constant object of Derived class and return non-void. +// Checking if arg is pointer on any of Derived classes: if(OBType(arg)) +// Applying Func can be done by two ways: +// 1) Function bool Apply(Res& res, args...). Here res is result of calling Func with arguments args. Result of Func is statically casted to type Res. +// If arg is not a pointer on any of Derived classes, Apply() return false and res is not changed. +// 2) Overloaded operator ()(args). It returns result of calling Func with arguments args. Type of returning value is type of Func(). +// Full definition. Never instantiated. +template class Func, class... O> +class OBTypeM; + +// Recursive partial instantiation +template class Func, class O1, class... O> +class OBTypeM: public OBTypeM +{ + bool right; + + OBTypeM() = delete; + OBTypeM(OBTypeM&&) = delete; + OBTypeM(OBTypeM&) = delete; + protected: + const ObjectBase* P() const {return OBTypeM::P();} + template + Res F(Args... args) const + { + if(right) return Func()(dynamic_cast(OBTypeM::P()),args...); + else return OBTypeM::template F(args...); + } + public: + OBTypeM(const ObjectBase* arg):OBTypeM(arg) {right=(typeid(*arg)==typeid(O1));} + operator bool() const {return right || OBTypeM::operator bool();} + template + bool Apply(Res& res, Args... args) const + { + if(!right) return OBTypeM::Apply(res,args...); + res=static_cast(Func()(dynamic_cast(OBTypeM::P()),args...)); + return true; + } + template + auto operator ()(Args... args) -> decltype(Func()(dynamic_cast(this->P()),args...)) const + { + typedef decltype(Func()(dynamic_cast(this->P()),args...)) T; + if(right) return Func()(dynamic_cast(OBTypeM::P()),args...); + else return OBTypeM::template F(args...); + } +}; + +// Partial instantiation of the bottom of recursion +template class Func> +class OBTypeM +{ + const ObjectBase* p; // We save pointer on bottom + OBTypeM() = delete; + OBTypeM(OBTypeM&&) = delete; + OBTypeM(OBTypeM&) = delete; + protected: // Only protected functions because such objects must never exists in the wild. + OBTypeM(const ObjectBase* arg):p(arg) {} + operator bool() const {return false;} // If we go down to this place, p is not an pointer on appropriate type + const ObjectBase* P() const {return p;} + template + bool Apply(Res& res, Args... args) const {return false;} + template + void operator ()(Args... args) const {} + template + Res F(Args... args) const {return Res();} +}; + + // Base class for all objects class EXPORT ObjectBase { @@ -45,23 +133,6 @@ public: }; -// Template for checking and using ObjectBase derivative classes -// Checking if arg is pointer on Derived: if(OBType(arg)) -// Using const ObjectBase* arg as const Derived*: OBType(arg)->SomeCall() -template -class OBType -{ - const O* p; - public: - OBType() = delete; - OBType(OBType&&) = delete; - OBType(OBType&) = delete; - OBType(const ObjectBase* arg) {if(typeid(*arg)==typeid(O)) p=dynamic_cast(arg); else p=0;} - const O* operator->() const {return p;} - operator bool() const {return 0!=p;} -}; - - // Template for objects without specific constructor/destructor template class EXPORT ObjectSimple: public ObjectBase