Sign in to follow this  

Template RTTI question

This topic is 4276 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

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

This topic is 4276 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this