Browse Source

Add template OBTypeM as multiple-types analog of OBType.

ObjPtr
Michael Uleysky 9 years ago
parent
commit
c4ff7d9233
  1. 105
      include/common.h

105
include/common.h

@ -18,6 +18,94 @@ EXPORT std::ostream& COUT(debug_level dl);
typedef std::set<std::string> UsedType;
class EXPORT ObjectBase;
// Template for checking and using ObjectBase derivative classes
// Checking if arg is pointer on Derived: if(OBType<Derived>(arg))
// Using const ObjectBase* arg as const Derived*: OBType<Derived>(arg)->SomeCall()
template<class O>
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<const O*>(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<Func,Derived>(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<Derived1>().
// Full definition. Never instantiated.
template<template<typename> class Func, class... O>
class OBTypeM;
// Recursive partial instantiation
template<template<typename> class Func, class O1, class... O>
class OBTypeM<Func,O1,O...>: public OBTypeM<Func,O...>
{
bool right;
OBTypeM() = delete;
OBTypeM(OBTypeM&&) = delete;
OBTypeM(OBTypeM&) = delete;
protected:
const ObjectBase* P() const {return OBTypeM<Func,O...>::P();}
template<class Res, class... Args>
Res F(Args... args) const
{
if(right) return Func<O1>()(dynamic_cast<const O1*>(OBTypeM<Func,O...>::P()),args...);
else return OBTypeM<Func,O...>::template F<Res,Args...>(args...);
}
public:
OBTypeM(const ObjectBase* arg):OBTypeM<Func,O...>(arg) {right=(typeid(*arg)==typeid(O1));}
operator bool() const {return right || OBTypeM<Func,O...>::operator bool();}
template<class Res, class... Args>
bool Apply(Res& res, Args... args) const
{
if(!right) return OBTypeM<Func,O...>::Apply(res,args...);
res=static_cast<Res>(Func<O1>()(dynamic_cast<const O1*>(OBTypeM<Func,O...>::P()),args...));
return true;
}
template<class... Args>
auto operator ()(Args... args) -> decltype(Func<O1>()(dynamic_cast<const O1*>(this->P()),args...)) const
{
typedef decltype(Func<O1>()(dynamic_cast<const O1*>(this->P()),args...)) T;
if(right) return Func<O1>()(dynamic_cast<const O1*>(OBTypeM<Func,O...>::P()),args...);
else return OBTypeM<Func,O...>::template F<T,Args...>(args...);
}
};
// Partial instantiation of the bottom of recursion
template<template<typename> class Func>
class OBTypeM<Func>
{
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<class Res, class... Args>
bool Apply(Res& res, Args... args) const {return false;}
template<class... Args>
void operator ()(Args... args) const {}
template<class Res, class... Args>
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<Derived>(arg))
// Using const ObjectBase* arg as const Derived*: OBType<Derived>(arg)->SomeCall()
template<class O>
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<const O*>(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 T>
class EXPORT ObjectSimple: public ObjectBase

Loading…
Cancel
Save