Template RTTI question

Started by
7 comments, last by Nitage 18 years ago
Hi. I just wanted to know to determine if an object is one of a particular template. Example:

class a
{
};
template<class T> class b : class a
{
};
In this case I would want to know if a pointer to an object of type a is actually a pointer to an object of type b. But as far as I can see you cant use a* ObjectOfTypeA .... typeid(*ObjectOfTypeA) == typeid(b) because you need to specify a class template parameter. Anyway, I'm not really sure about any of this - Even if you can have a template class inherit from a non-template class. Thanks in advance.
Advertisement
Template classes are used to create actual classes at compile time. So, there isn't really a "class b" in your program, but rather many different "class b"s; one for each type that you give it as a template parameter. So, if you know what types you're instantiating at compile time, maybe you could do some kind of monstrosity using if typeid(objectA)==typeid(b<std::string>) or whatnot. In fact, I don't even know if that would work, I don't really use the oft overlooked typeid operator. Runtime type inferences are alot more suited to something like Java, but that's not really the point here.

That being said, getting access to types at runtime is not exactly one of C++'s strong points, so I think one of the quick 'n dirty ways to do what you're wanting to do is to tag class a and class b with some field that identifies which each one is.
You have to use typeid( b ) etc., there is no way to omit the template-parameter, because b itself is only a template and b is a class of the b-template with int as instantiated argument.
Ok Thanks for the replies - I already had that bit. So basically theres NO way to fix this? One way would be if there is a way to figure out if a class is a sub-class of a given class?
If you only need to do this statically take a look at the boost::type_traits library. Since it looks like you need to do this dynamically the only way I can think of will be to include it in your class design. Something like this:

class a{public:    virtual bool is_b() { return false; }};template<typename T> class b : public a{public:    virtual bool is_b() { return true; }};


This is a very inflexible solution (what if you need to know if it's actually a class c?) but should give you some ideas that will better suit your situation. The question you really need to ask yourself though is why do you need to know if an instance is of the template b? You may be able to work out a better design where this isn't needed, usually class a would provide an interface that would make it unnecessary to know what the derived type is.
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
There is no good solution for this problem. I think that solutions which require you to change "a" is very bad, since "a" might not be your class, but a third-party class you are deriving from. The following is how I would do it:
#include <cassert>class a{public:	virtual ~a(){}};template<typename T>class b;class b_base : public a{	template<typename T>	friend class b;private:	b_base(){}	virtual ~b_base(){};};template<typename T>class b : public b_base{};bool is_type_b(a* in){    return ( dynamic_cast<b_base*>(in)!= 0 );}int main(){	a* a_ptr_type_a = new a;	b<int>* a_ptr_type_b = new b<int>;	assert( false == is_type_b(a_ptr_type_a) );	assert( true == is_type_b(a_ptr_type_b) );	return 0;}

what we do is that we have a class between a and b<T> (b_base) and checks whether we can cast a to b_base, if we can that must mean that the object is of type b<T>. It can't be b_base because noone but b<T> can actually construct or destruct b_base (private constructor and destructor, b<T> is friend). Also it can't be another class deriving from b_base since no other class than b<T> is allowed to do that.
Awsome CTar, thats just what I was looking for. I know dynamic_cast returns 0 if the cast is impossible, does using dynamic_cast impose any sort of significant overhead?

This is for part of a computer algebra system, so its possible speed might be an issue, i wont know until my first test-run.
Quote:Original post by DaBookshah
Awsome CTar, thats just what I was looking for. I know dynamic_cast returns 0 if the cast is impossible, does using dynamic_cast impose any sort of significant overhead?

This is for part of a computer algebra system, so its possible speed might be an issue, i wont know until my first test-run.


If you need to know the exact type of a polymorphic type then something is most likely wrong with your design, if you could tell us what you want to achieve with it someone might be able to propose a better technique. dynamic_cast could hurt your performance if you use it a lot, so it depends on what you want to do. For example if you have a base class vector and derived classes vector_SSE, vector_3DNow and vector_std. Now if you have a function like this:
vector* multiply(vector*,vector*);
Which internally use dynamic_cast to cast the vector pointer to the actual class and take advantage of the way the data is stored, then you will most likely experience performance problems because of the dynamic_cast.
If you have a base class algebra_system and derived classes fast_algebra_system (get extra performance, but use more memory) and small_algebra_system (use very little memory). In this case you are very unlikely to do the dynamic_cast a lot of times, and it wont hurt performance.
How about:
class A{  //whatever - you might not have control over this};class B : public A{    virtual ~B()=0;//so this can't be instantiated };template < class T >class C : public B{  //whatever};


So you could add another layer of inheritance, then do:
typeid(*ptrToA) == typeid(B) to test if the pointer points to an instantiation of C.

The downside is that there's nothing stopping anyone else deriving from class B - you might be able to control that with private c'tors/d'tors.

This topic is closed to new replies.

Advertisement