Есть следующая проблема. Паттерн визитер вызывает метод только для конкретного класса. А мне нужно проходиться по всей иерархии класса и вызывать метода для предка класса, если такой есть. К примеру есть человек и есть у от него унаследованный класс сотрудник, а от сотрудника унаследован класс уборщица. Есть у нас контейнер указателей не людей. И там есть уборщицы и сотрудники. И есть у нас визитер, который может отрабатывать либо на уборщицах. Либо на людях. Так вот, проблема возникает, когда я пытаюсь обратиться на уровень выше при вызове метода TParentVisitorCaller::make_call, компилятор не может понять метод какого класса ему нужно вызвать. То ли у сотрудника, то ли у уборщицы. Подскажите кто ни-будь может подсказать, как это по проще сделать: объяснить компилятору, что нужно сначала вызвать метод у сотрудника, если нет метода у уборщицы. Код | #ifndef VISITOR_TEMPLATES_H #define VISITOR_TEMPLATES_H
#include "cdefaultvisitor.h" #include <type_traits> #include <typeinfo>
template<typename TCurrentClass, typename TParentClass> class TParentVisitorCaller { public:
static bool make_call(TCurrentClass& obj, CVisitor& visitor) { static_assert(std::is_base_of<TParentClass, TCurrentClass>::value, "TParentClass is not base class of TCurrentClass"); TParentClass& parentObj = obj; return parentObj.static_visit(visitor); }
static bool make_call(const TCurrentClass& obj, CVisitor& visitor) { static_assert(std::is_base_of<TParentClass, TCurrentClass>::value, "TParentClass is not base class of TCurrentClass");
const TParentClass& parentObj = obj; return parentObj.static_visit(visitor);
} };
template<typename TCurrentClass> class TParentVisitorCaller < TCurrentClass, void > { public: static bool make_call(TCurrentClass& obj, CVisitor& visitor) { return false; }
static bool make_call(const TCurrentClass& obj, CVisitor& visitor) { return false; } };
template<typename TCurrentClass,typename TParentClass=void> class TMakeVisitable { public: virtual void visit(CVisitor& visitor)const { static_visit(visitor); }
virtual void visit(CVisitor& visitor) { static_visit(visitor); }
bool static_visit(CVisitor& visitor)const { typedef decltype(static_cast<const TCurrentClass&>(*this)) TThisConstRefernceType; typedef std::remove_reference<TThisConstRefernceType>::type TThisTypeReference; typedef std::remove_const<TThisTypeReference>::type TThisType; TVisitor<TThisType>* visitorOfType = dynamic_cast<TVisitor<std::remove_const<TThisType>::type>*>(&visitor); if (visitorOfType) { visitorOfType->make_visit(static_cast<const TCurrentClass&>(*this)); return true; } else { //return TParentVisiterCaller<TCurrentClass, TParentClass>::make_call(static_cast<const TCurrentClass&>(*this), visitor); } return false; } bool static_visit(CVisitor& visitor) { typedef decltype(static_cast<TCurrentClass&>(*this)) TThisTypeReference; typedef std::remove_reference<TThisTypeReference>::type TThisType; TVisitor<TThisType>* visitorOfType = dynamic_cast<TVisitor<TThisType>*>(&visitor); if (visitorOfType) { visitorOfType->make_visit(static_cast<TCurrentClass&>(*this)); return true; } else { return TParentVisitorCaller<TCurrentClass, TParentClass>::make_call(static_cast<TCurrentClass&>(*this), visitor); } return false; } protected: TMakeVisitable() { }
TMakeVisitable(const TMakeVisitable& obj) { }
TMakeVisitable& operator=(const TMakeVisitable& obj) { return *this; } };
#endif
|
Вот пример использования кода: Код | class A1 :public TMakeVisitable < A1 > {
};
class B1 :public A1,public TMakeVisitable < B1, A1 > { };
class C1 :public B1, public TMakeVisitable < C1, B1 > { };
|
--------------------
Постоянно удивляюсь человеческой фантазии напридумывают гаджетов
|