2012-05-16 3 views
0

Я пытаюсь использовать boost::is_base_of, чтобы определить, может ли базовый класс CRTP Generic идентифицировать своих сверстников, то есть классы, которые также получены от T.Обнаружение братьев и сестер базового класса CRTP

Как показано в Generic<T>::init(), я хотел бы использовать эти механизмы для того, чтобы класс Generic<T> добавить указатели на функции одного из его коллег Bar1 или Bar2 (из которых T также происходит) на карте. К сожалению, boost::is_base_of не может обнаружить классы, такие как Bar3, что T не происходит.

#include <iostream> 
#include <cstdlib> 
#include <string> 
#include <typeinfo> 
#include <map> 
#include <boost/type_traits.hpp> 

////////////////////////////////////////////////////////////////////////////////////// 

template<typename T> 
class Bar 
{ 
public: 
    void setValue() 
    { 
     std::cout << typeid(this).name() << std::endl; 
    } 
}; 

class Bar1 : public Bar<char>{}; 
class Bar2 : public Bar<bool>{}; 
class Bar3 : public Bar<long>{}; 

////////////////////////////////////////////////////////////////////////////////////// 

template<typename T> 
class Generic 
{ 
public: 
    typedef void (T::*setter)(); 
    void init(); 
}; 

template<typename T> 
void Generic<T>::init() 
{ 
    std::map<std::string , Generic<T>::setter> setterMap; 
    if(boost::is_base_of<Bar1, T >::value) setterMap["bar1"] = &Bar1::setValue; 
    if(boost::is_base_of<Bar2, T >::value) setterMap["bar2"] = &Bar2::setValue; 
    if(boost::is_base_of<Bar3, T >::value) setterMap["bar3"] = &Bar3::setValue; 
    std::cout << setterMap.size() << std::endl; 
} 

////////////////////////////////////////////////////////////////////////////////////// 

template<typename T> 
class Foo : public Bar1 , public Bar2 , public Generic<Foo<T> > 
{ 
public: 

}; 

////////////////////////////////////////////////////////////////////////////////////// 

int main() 
{ 
    Foo<int> f; 
    f.init(); 

    return EXIT_SUCCESS; 
} 

////////////////////////////////////////////////////////////////////////////////////// 

НКУ сообщение об ошибке:

In static member function ‘static void Generic<T>::init() [with T = Foo<int>]’: 
error: cannot convert ‘void (Bar<long int>::*)()’ to ‘void (Foo<int>::*)()’ in assignment 

Редактировать

Чтобы обеспечить некоторый контекст для этого вопроса. Я пытаюсь сохранить указатели на методы setValue базовых классов каждого Foo<T> на карте для быстрого доступа. Выбор setValue для вызова зависит от строки, таким образом, от карты. Другой класс X может наследовать Bar1 и Bar3, но не Bar2, и, как и прежде, мне нужно было бы сохранить указатели на соответствующий setValue для быстрого доступа. Generic<T> стремится выполнять эту роль Foo, X и т.д.

ответ

1

Jay является правильным. Я сделал следующие изменения, и это, похоже, работает.

template <bool, typename T> struct AddSetter; 

template <typename T> struct AddSetter <true, T> 
{ 
    template<typename F> 
    void Set (std::map<std::string , typename Generic<T>::setter>& setterMap, const std::string& key, F fn) 
    { 
     setterMap[key] = fn; 
    } 
}; 

template <typename T> struct AddSetter <false, T> 
{ 
    template<typename F> 
    void Set (std::map<std::string , typename Generic<T>::setter>& setterMap, const std::string& key, F fn) 
    { 
    } 
}; 

template<typename T> 
void Generic<T>::init() 
{ 
    std::map<std::string , Generic<T>::setter> setterMap; 
    AddSetter<boost::is_base_of<Bar1, T >::value, T>().Set (setterMap, "bar1", &Bar1::setValue); 
    AddSetter<boost::is_base_of<Bar2, T >::value, T>().Set (setterMap, "bar2", &Bar2::setValue); 
    AddSetter<boost::is_base_of<Bar3, T >::value, T>().Set (setterMap, "bar3", &Bar3::setValue); 
    std::cout << setterMap.size() << std::endl; 
} 
+1

Наконец-то! Могу ли я получить голосование? Кстати, кто твой папа? Давай теперь ... скажи мне: P – Jay

+1

Кстати, хороший пример ... У меня не было времени с тех пор, как я был в спешке, чтобы курить сорняк – Jay

1

Off верхней части моей головы, я просто не могу представить себе эту работу без среднего человека ...

Можно ли создать-структуру, которая инкапсулирует нужная логика с перегрузкой оператора? Структура будет иметь необработанный указатель, а затем вы можете почтить его перегрузкой, чтобы убедиться, что она была использована правильно.

Другой, казалось бы, читаемый способ - создать еще один класс перед лицом, который действует как Фасад, а затем использовать его.

Это похоже на Override contra-variance workaround needed

+0

Спасибо! Я почти могу голосовать сейчас! – Jay

Смежные вопросы