views:

76

answers:

2

I could of course use is_base if the base class where not a template. However, when it is, I just don't see any way to generically match any derived type. Here's a basic example of what I mean:

#include <boost/mpl/bool.hpp>

template < typename T >
struct test_base
{
};

template < typename T >
struct check : boost::mpl::false_ {};

template < typename T >
struct check<test_base<T> > : boost::mpl::true_ {};

struct test_derived : test_base<int> {};

#include <iostream>
int main() 
{
  std::cout << check<test_derived>::value << std::endl;
  std::cin.get();
}

I want that to return true_ rather than false_. The real example has like 7 template parameters, most defaulted, and uses Boost.Parameter to refer to them by name. In order to use is_base I'd have to be able to pull the parameters out somehow and I don't see a way to do that short of declaring internal typedefs.

I think it's impossible. Looking to be proven wrong.

A: 

Here. You may change is_base_and_derived for is_same, depending on the needs.

#include "boost/mpl/equal.hpp"
#include "boost/mpl/vector.hpp"
#include <boost/utility/enable_if.hpp>
#include "boost/type_traits/is_base_and_derived.hpp"
#include <boost/function_types/function_type.hpp>

using namespace boost;

template < typename T >
struct test_base
{
};

struct test_derived : test_base<int> {};


//The default case
template<class T, class Enable =void>
class check : public boost::mpl::false_ {};

//The specified case
template<class T>
class check<T, typename boost::enable_if<
         boost::is_base_and_derived<test_base<int>,T>
    >::type>: public boost::mpl::true_  
{};


#include <iostream>
int main() 
{
    std::cout << check<test_derived>::value << std::endl;
    std::cin.get();
}
Alexandre Deschamps
Thanks, but... That only works if you pass it something derived from test_base<int>, it doesn't work for any test_base. Object is to match anything derived from any instantiation of test_base.
Noah Roberts
Ish, sorry i went too fast. Then I just don't see how you could do that. Event if it's ugly, maybe an alternative would be to add an empty interface to do your is_base_and_derived on.
Alexandre Deschamps
+1  A: 

You just need to tweak your test a bit:

#include <iostream>
#include <boost/mpl/bool.hpp>

template < typename T >
struct test_base
{
};

template < typename T >
struct check_
{
    template<class U>
    static char(&do_test(test_base<U>*))[2];
    static char(&do_test(...))[1];
    enum { value = 2 == sizeof do_test(static_cast<T*>(0)) };
};

template < typename T >
struct check : boost::mpl::bool_<check_<T>::value> {};

struct test_derived : test_base<int> {};

int main()
{
  std::cout << check<test_derived>::value << std::endl;
}
Maxim Yegorushkin
Excellent! SFINAE to the rescue yet again.
Noah Roberts
SFINAE is not involved here, just pure function overloading. I.e. instantiating do_test(test_base<U>*) never produces an error.
Maxim Yegorushkin