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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как найти базовый класса для данного класса, Нужно какому интерфейсу можно привести? 
:(
    Опции темы
Empirik
Дата 29.6.2014, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Делаю свою реализацию паттерна Visitor. Точнее его подвида Static Visitor. Но есть одна проблема. Нужно, что бы если в посетителе нет класса для нужного метода, хотелось бы что бы посетитель находил метод с ближайшим предком для данного объекта и вызывал метод для него. Как решить эту задачу я пока не знаю. 

Задачу нахождения визитера под конкретный тип решаю при помощи макроса. 

Код

#define MAKE_VISITABLE \
    virtual void visit(CVisitor& visitor)const{\
    typedef decltype(*this) TThisConstRefernceType;\
    typedef std::remove_reference<TThisConstRefernceType>::type TThisTypeReference;\
    typedef std::remove_const<TThisTypeReference>::type TThisType; \
    static CVisitableClassInfo<TThisType> classMeta;\
    TVisitor<TThisType>* visitorOfType = dynamic_cast<TVisitor<std::remove_const<TThisType>::type>*>(&visitor);\
    if (visitorOfType)\
    {\
        visitorOfType->make_visit(*this); \
    }else\
    {\
    std::cout << "can't handle class " << typeid(*this).name() << " " << typeid(TThisType).name()<<std::endl; \
    }\
    }\
    virtual void visit(CVisitor& visitor){\
    typedef decltype(*this) TThisTypeReference; \
    typedef std::remove_reference<TThisTypeReference>::type TThisType; \
    TVisitor<TThisType>* visitorOfType = dynamic_cast<TVisitor<TThisType>*>(&visitor);\
    if (visitorOfType)\
    {\
    visitorOfType->make_visit(*this); \
    }\
    else\
    {\
    std::cout << "can't handle class " << typeid(*this).name() << " " << typeid(TThisType).name() << std::endl; \
    }\
    \
    }\
    template<typename CType> bool is_can_convert_to()const\
    {\
        typedef decltype(*this) TThisConstRefernceType; \
        typedef std::remove_reference<TThisConstRefernceType>::type TThisTypeReference; \
        typedef std::remove_const<TThisTypeReference>::type TThisType; \
        return std::is_base_of<CType, TThisType>::value;\
    }\


Как бы вы решили задачу нахождение визитера ближайшего родителя для данного класса? 
--------------------
Постоянно удивляюсь человеческой фантазии напридумывают гаджетов
PM MAIL WWW ICQ   Вверх
Lukkoye
Дата 30.6.2014, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 23.3.2013

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



Не совсем понятно, зачем и чего вы там ищете.

Если у вас есть и иерархия классов, и вам просто нужно времени компиляции определить доступен ли метод указанного имени и указанной сигнатуры, то вы можете воспользоваться моим SFINAE-детектором.

Для этого вам понадобится поддержка с++11


Мой детектор корректно умеет обрабатывать перегрузку функций-членов.
При этом учитывает что функция член может иметь квалификатор const.

Правила доступности - аналогичны правилам доступности методов в языке с++


Есть проблемы для компиляторов вижал студии (плохая поддержка стандарта с++11)
Подробности вы можете узнать здесь:
http://www.gamedev.ru/code/forum/?id=184871

http://ideone.com/ObElnu


Код

#include <iostream>
#include <type_traits>
 
using namespace std;
 
 
#define DETECTED_MEMBER(member_name)                                                      \
template<typename C, typename T>class has_##member_name                                   \
{                                                                                         \
    template<class U> static constexpr auto Check(U*) -> typename                         \
    std::is_same< decltype( std::declval<U>().member_name), T >::type;                    \
                                                                                          \
    template<typename> static constexpr std::false_type Check(...);                       \
    typedef decltype(Check<C>(0)) Result;                                                 \
public:                                                                                   \
    enum { eIS_NOCONST = 0 };                                                             \
    enum { eIS_CONST   = 0 };                                                             \
    enum { eIS_AVAILABLE = Result::value };                                               \
};                                                                                        \
template<class C,typename R, typename... Args>class has_##member_name<C, R(Args...)>      \
{                                                                                         \
    typedef R(C::*Method)(Args...);    typedef R(C::*CMethod)(Args...)const;              \
    template <class U> using NoConst = decltype(static_cast<Method> (&U::member_name));   \
    template <class U> using Const   = decltype(static_cast<CMethod>(&U::member_name));   \
                                                                                          \
    template<class U> static constexpr std::true_type  CheckNoConst( NoConst<U>*p );      \
    template<class>   static constexpr std::false_type CheckNoConst(...);                 \
    typedef decltype(CheckNoConst<C>(0)) NoConstResult;                                   \
                                                                                          \
    template<class U> static constexpr std::true_type  CheckConst( Const<U>*p);           \
    template<class>   static constexpr std::false_type CheckConst(...);                   \
    typedef decltype(CheckConst<C>(0)) ConstResult;                                       \
public:                                                                                   \
    enum { eIS_NOCONST = NoConstResult::value      };                                     \
    enum { eIS_CONST   = ConstResult::value        };                                     \
    enum { eIS_AVAILABLE = eIS_NOCONST | eIS_CONST };                                     \
};
 
#define is_available(class_name, member_type, member_name)         has_##member_name<class_name, member_type>::eIS_AVAILABLE
#define is_available_method(class_name, member_type, member_name)  has_##member_name<class_name, member_type>::eIS_NOCONST
#define is_available_cmethod(class_name, member_type, member_name) has_##member_name<class_name, member_type>::eIS_CONST
 
//------------------------------------------------------------------------------------
 
 
int g;
struct A  //<---- для эксперимента будем определять доступность методов и данных
{
    A():r(g){}
 
    void fooA(int);
    void fooA(int)const;
    void fooA();
    void fooA()const;
 
    int v;
    int& r;
    int a[10];
    int* p;
    int** pp;
private:
    void private_foo();
};
 
struct B : A   //<---- используем наследование, 
{              //что бы продемонстрировать определение доступности методов в базовых классах
    int v;
    int fooB(){ return 0; }
};
 

//указываем имена мемберов, доступность которых хотим определить
DETECTED_MEMBER(fooA);
DETECTED_MEMBER(fooB);
DETECTED_MEMBER(v);
DETECTED_MEMBER(r);
DETECTED_MEMBER(a);
DETECTED_MEMBER(p);
DETECTED_MEMBER(pp);
 
DETECTED_MEMBER(private_foo);
 
 
int main()
{
    //синтаксис:  is_available(  имя_класса ,  тип_мембера  , имя_мембера)
 
    //вернет true если мембер доступен, иначе - false
 
    //---- детектирование данных
    cout<< "is available int B.v ? "
        << is_available(B,int,v)     <<endl;
 
    cout<< "is available int& B.r ? "
        << is_available(B,int&,r)    <<endl;
 
    cout<< "is available int B.a[10] ? "
        << is_available(B,int[10],a) <<endl;
 
    cout<< "is available int* B.p ? "
        << is_available(B,int*,p)    <<endl;
 
    cout<< "is available int* B.pp ? "
        << is_available(B,int**,pp)  <<endl;
 
    //---- детектирование методов
    cout<< "is available void B.fooA(int) or void B::fooA(int)const ? "
        <<is_available(B,void(int),fooA) <<endl;
 
    cout<< "is available void B.fooA(int) ? "
        << is_available_method(B,void(int),fooA) <<endl;
 
    cout<< "is available void B.fooA(int)const ? "
        << is_available_cmethod(B,void(int),fooA) <<endl;
 
    cout<< "is available int B.fooB() ? "
        << is_available_method(B,int(),fooB) <<endl;
 
    cout<< "is available void B.private_foo() ? "      
        << is_available(B,void(),private_foo) <<endl;
}





Это сообщение отредактировал(а) Lukkoye - 30.6.2014, 22:19
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0593 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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