I am trying to use boost::is_base_of
in order to detect if a CRTP base class Generic
can identify its peers i.e. classes that T
is also derived from.
As shown in Generic<T>::init()
, I would like to use these mechanisms in order to allow the class Generic<T>
add pointers to functions one of its peers Bar1
or Bar2
(from which T
also derives) to a map. Unfortunately boost::is_base_of
is unable to detect classes, such as Bar3
, that T
does not derive from.
#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;
}
//////////////////////////////////////////////////////////////////////////////////////
gcc error message:
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
Edit
To provide some context for this question. I'm trying to store pointers to the setValue
methods of the base classes of each Foo<T>
in a map for quick access. The choice of setValue
to call depends on a string, thus the map. Another class X
may inherit Bar1
and Bar3
but not Bar2
, and as before I would have to store pointers to the appropriate setValue
's for quick access. Generic<T>
aims to fulfil this role for Foo
, X
etc.