Victor Liu
Victor Liu

Reputation: 3643

How to have templated function overloads accept derived classes from different base classes?

I want to be able to define

template <class TX>
void f(const TX &x){ ... }
template <class TY>
void f(const TY &x){ ... }

where TX must be derived from BaseX and TY must be derived from BaseY (how do I specify this kind of thing?), and I want to be able to call it as

f(DerivedX<T>())

It is most important that I can avoid specifying the template parameters. Is this possible, and if so how would I implement it? If it's not possible, is there a way I can make a templated function accept only certain types, but still have it be implicitly instantiated? I cannot just make the overloads of f accept the base class because I need the derived class' type.

Upvotes: 2

Views: 234

Answers (2)

James McNellis
James McNellis

Reputation: 355069

You can use is_base_of from Boost.TypeTraits like so:

#include <boost/type_traits.hpp>
#include <boost/utility.hpp>

class BaseX { };
class BaseY { };

class DerivedX : public BaseX { };
class DerivedY : public BaseY { };

template <typename TX>
boost::enable_if<boost::is_base_of<BaseX, TX>, void>::type
f(const TX& x) 
{
}

int main(int argc, char** argv)
{
    DerivedX x;
    DerivedY y;

    f(x); // compiles
    f(y); // will cause a compilation error
}

The Boost.TypeTraits library is header-only, so you don't need to link anything in.

Upvotes: 6

Jonathan Graehl
Jonathan Graehl

Reputation: 9301

template <class TX>
void f(const BaseX &x){ ... }
template <class TY>
void f(const BaseY &x){ ... }

f<DerivedX>(DerviedX<T>())

That seems easiest to me. You could use boost's is_base_of if you don't want to supply the explicit template argument.

Upvotes: -1

Related Questions