Sign in to follow this  
Oiu1233

C++ Run-Time Type ID brain fart.

Recommended Posts

Oiu1233    134
I was looking for a way to automatically generate a run-time ID for any and every types. I came up with this:
template < typename _Type >
struct TypeRTID
{
	static size_t const m_id;
};
template < typename _Type >
size_t const TypeRTID < _Type > ::m_id = (size_t const) &TypeRTID < _Type > ::m_id;
you can use it like this:
size_t const floatRTID = TypeRTID < float > ::m_id;
size_t const floatPtrRTID = TypeRTID < float * > ::m_id;

Share this post


Link to post
Share on other sites
silvermace    634
That's pretty nifty, seems to work on Visual C++ 2008 just fine..

I love that in C++, you learn something new all the time, regardless how long you've been using it [smile].

-Danu

Share this post


Link to post
Share on other sites
frob    44903
Quote:
Original post by Oiu1233
I was looking for a way to automatically generate a run-time ID for any and every types.
Why?

There are very few times that you need this kind of ID, and those few times (such as serialization) can be handled easily through a base class.

Share this post


Link to post
Share on other sites
owl    376
So, in short, you'd be using the address of the static member to identify the type at runtime?

Looks interesting. Are there any drawbacks to this?

Share this post


Link to post
Share on other sites
silvermace    634
From what I can tell, it would fall short of polymorphic types. TypeID has a dynamic component which incurs runtime cost but will give you a more useful result.

This method ensures static compilation, but because of that its probably a little limited in non-trival use-cases.

Share this post


Link to post
Share on other sites
frob    44903
Quote:
Original post by owl
Are there any drawbacks to this?
There always are.


It creates a static instance of every object. This may be an issue if you have large objects or nontrivial constructors.

The type must allow external linkage. It is possible to give a typename that has no linkage or internal linkage, and experienced template metaprogrammers use those. They would break the system.

Dynamic linking will give different results. Each module will have a different static instance, so provide different answers.

The value may differ between builds. It is quite likely that the addresses will change, and an id from one build may refer to a completely different type in another build, or refer to no object whatever.

There is broad liberty for the compiler as to how to interpret template type names. It is possible to have names unexpectedly merged, or types that you would expect to be merged end up distinctively different. If you use template types or typedef names it may be expanded to various unkonwn degrees.

Don't discount compiler bugs: there are still some linkers out there that will not properly merge duplicate templates.




There are very few reasons where you need to get an actual type id at runtime, and most of those can be handled through more reliable solutions.

Share this post


Link to post
Share on other sites
Hodgman    51220
This is neat, thanks for sharing.

I use a similar system, but mine's based on doing a hash of typeid(t).name(), which still requires you to have RTTI enabled.
Quote:
Original post by Codeka
What does that give you over the standard typeid operator?
typeid requires RTTI to be enabled in your compiler, which increases the size of your binaries. Not usually a problem, but some consoles do recommend disabling RTTI.

Also, MSVC is really slow at doing comparisons between type_info structures (lots and lots of strcmps!). Sometimes a lightning fast (but restricted -- no polymorphism) type compare comes in handy.
Quote:
Original post by frob
There are very few times that you need this kind of ID, and those few times (such as serialization) can be handled easily through a base class.
What if you don't want to have the requirement of all serializable objects having a common base class? (e.g. I want my lightweight Vec4 class to be serializable...)

Like you point out above though, the fact that the IDs can change makes this unsuitable to serialization to files (still good for network replication though).

[Edited by - Hodgman on November 11, 2009 5:50:39 PM]

Share this post


Link to post
Share on other sites
SiCrane    11839
I think the biggest problem is that assignment of IDs isn't guaranteed to happen before they're used. So before main() they could be set to zero and if you have other code using implicit initialization like this that depends on your IDs you could have subtle, hard to debug issues emerge.

Share this post


Link to post
Share on other sites
Sc4Freak    643
Quote:
Original post by frob
Quote:
Original post by owl
Are there any drawbacks to this?
There always are.

It creates a static instance of every object. This may be an issue if you have large objects or nontrivial constructors.


Does it really? Objects of type _Type are never actually instantiated. The only thing that will be constructed is the size_t - one for each different _Type you use. Large objects or nontrivial constructors for _Type don't really seem like issues here.

Share this post


Link to post
Share on other sites

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