Jump to content
  • Advertisement
Sign in to follow this  
seifer503

c++ determine if template paramater is of polymorphic type

This topic is 3884 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This might be really simple but I'm trying to determine if a template parameter implements a certain interface.

class Interface {
   virtual void f() = 0;
};

template<class T>
class C {
   void g(const T &t) {
      //if T has base class type, do something
     //otherwise, do something else
   }
};


I tried a specialization but it seems to only detect the static type, which is the derived class.
template<>
class C <Interface> {
  void g(const Interface &t) {
     //since Interface is an abstract base class, no object will actually
     //have this static type
  }
}

I also tried dynamic_cast() in the base template above, but it will not compile on non polymorphic types. Anyone know a good way to accomplish this?

Share this post


Link to post
Share on other sites
Advertisement
The only way I know of is via some template wizardry... I got this from somewhere else myself, I can't remember the source though:


template<class b, class a>
class InheritsFrom
{
private:

typedef u8 Small;
typedef u16 Big;
static Small TestIfBIsA( const a& );
static Big TestIfBIsA( ... );
static b fMakeB( );

public:

enum { IsSubClass = ( sizeof( TestIfBIsA( MakeB( ) ) ) == sizeof( Small ) ) };

};

#define CanConvert(b,a) InheritsFrom<const b*, const a*>::IsSubClass


This then allows you to specialize templates based on a bool, wherein you pass the compile-time constant CanConvert(SomeClass,YourPolymorphicBaseClass). I.e.,


template<class T, bool isPolymorphic>
class A
{
void g( const T& t )
{
// this is the non-polymorphic version
}
};

template<class T>
class A<T,true>
{
void g( const T& t )
{
// this is the polymorphic version
}
};

You would instantiate the template using the following

A<SomeClass,CanConvert(SomeClass,Interface)> a;

Share this post


Link to post
Share on other sites
there are a number of ways to accomplish this, but the simplest is to use function overloading.



class Interface {
virtual void f() = 0;
};

template<class T>
class C {
void g(const T &t) {
cout << "unknown type";
}

void g(const Interface &t) {
cout << "Interface";
}
};

int main()
{
std::string s;
SomeInterfaceDerivedClass c;

C template;

template.g(s); // prints "unknown type"
template.g(c); // prints "Interface"
}




This isn't fool proof though, but it might be enough for what you need.

Post again if it isn't.

Share this post


Link to post
Share on other sites
Quote:
Original post by seifer503
This might be really simple but I'm trying to determine if a template parameter implements a certain interface.


Yes.

#include <boost/type_traits.hpp>
const bool example = boost::is_base_of< Interface, PossiblyDerived >::value;

Share this post


Link to post
Share on other sites
emeyex, that code did just what I needed. It makes perfect sense to use the function overload mechanism and compare the size of the return types. I would never have thought of that. However, I do get a compiler warning: warning #1595: non-POD (Plain Old Data) class type passed through ellipsis. I guess this is unavoidable?

Share this post


Link to post
Share on other sites
Quote:
Original post by seifer503
emeyex, that code did just what I needed. It makes perfect sense to use the function overload mechanism and compare the size of the return types. I would never have thought of that. However, I do get a compiler warning: warning #1595: non-POD (Plain Old Data) class type passed through ellipsis. I guess this is unavoidable?


It's avoidable. Change the TestIfBIsA() that takes a reference to take a pointer instead. You'll get the same effect. It is legal for compilers to reject the reference-based code.

I'd recommend you use boost type_traits, as already suggested. It works around this and many other nasty little issues.

Share this post


Link to post
Share on other sites
Thank you, the_edd! I always miss the obvious. One of the these days I'll have to check out this whole boost thing everyone is talking about.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!