Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Реализация Static Visitor на шаблонах, Как наладить диспетчирезацию  
:(
    Опции темы
Empirik
Дата 17.5.2015, 07:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 156
Регистрация: 28.10.2005
Где: Россия, Пермь

Репутация: нет
Всего: 1



Есть следующая проблема. Паттерн визитер вызывает метод только для конкретного класса. А мне нужно проходиться по всей иерархии класса и вызывать метода для предка класса, если такой есть. 

К примеру есть человек и есть у от него унаследованный класс сотрудник, а от сотрудника унаследован класс уборщица. Есть у нас контейнер указателей не людей. И там есть уборщицы и сотрудники. И есть у нас визитер, который может отрабатывать либо на уборщицах. Либо на людях. 

Так вот, проблема возникает, когда я пытаюсь обратиться на уровень выше при вызове метода 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 >
{
};

--------------------
Постоянно удивляюсь человеческой фантазии напридумывают гаджетов
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0565 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.