   std::type_info and references
  I've just noticed that (at least on MSVC9) type_info structures for reference types are the same as their non-reference counterparts. In other words:{assert( typeid(int) != typeid(int*) )//PASSassert( typeid(int) != typeid(int&) )//FAILassert( strcmp(typeid(int).name(), typeid(int*).name()) != 0 )//PASSassert( strcmp(typeid(int).name(), typeid(int&).name()) != 0 )//FAIL}Is this by design in C++? Can someone help me understand why my expectations are wrong?I only noticed this because I'm using hashes based on typeid(T).name() *a lot* in my data-driven stuff, like factories, RPC, script bindings, etc...I've quickly patched up my GetHash function to work, but I was wondering if there's some other way:template<class T> struct IsReference { const static bool value = false; };template<class Y> struct IsReference< Y&> { const static bool value = true;  };template<class Y> struct IsReference<const Y&> { const static bool value = true;  };template<class T> inline uint32 GetHash(){const char* sz = typeid(T).name();//Here be my fix:char buf[1024];if( IsReference<T>::value ){assert( strlen(sz) < 1022 )strcpy( buf, sz );strcat( buf, "&" );sz = buf;}//End of my fixuint32 h = TypenameToHash( sz );DEBUG( dbgCheckForNameCollisions_( h, sz ); )return h;}[edit]Just realised const doesnt change the type name either, except pointer-to-const:assert( typeid(const int ) != typeid(int ) )//FAILassert( typeid(const int*) != typeid(int*) )//PASSassert( typeid(int* const) != typeid(int*) )//FAILassert( typeid(const int&) != typeid(int&) )//FAIL
§5.2.8 - 5:typeid(D) == typeid(const D&); //yields true.note that the top-level CV qualifiers are always ignored.   ;  Thanks Washu -- so it's by design then.I've got a RPC-type mechanism somewhat simmilar to boost::bind, where it takes the arguments given to it and stores them in an internal structure that can be passed around and later executed. One of the inputs to this system is the type_infos of the target function's arguments, which is why I was hoping for references to be a different type - when the user sets these arguments I have to know whether to store a pointer to their data (for references) or the data itself. Hopefully my IsReference extension will suffice.   ;Quote:Original post by HodgmanThanks Washu -- so it's by design then.I've got a RPC-type mechanism somewhat simmilar to boost::bind, where it takes the arguments given to it and stores them in an internal structure that can be passed around and later executed. One of the inputs to this system is the type_infos of the target function's arguments, which is why I was hoping for references to be a different type - when the user sets these arguments I have to know whether to store a pointer to their data (for references) or the data itself. Hopefully my IsReference extension will suffice.Your template solution (I use boost::is_reference/std::is_reference from type traits), is about the only workable solution.   ;  The reason for this behavior is that typeid and type_info are part of C++'s RTTI mechanism. So when you call typeid on a reference, you're asking what the dynamic type of the object the reference is bound to, not the static type of the reference itself. So for consistency if you call typeid on a reference type you get the typeid of the type referred to instead of the reference.   ;  So why don't you simply use a pointer instead of a reference?   ;  Thanks for the responses =DQuote:Original post by DevFredSo why don't you simply use a pointer instead of a reference?Like I said, one of the inputs to my RPC system is a list of type-hashes corresponding to the arguments to the function. Actually, before I said I had a list of type_infos - I actually have a list of hashes that I generate from the posted GetHash function (which uses the type_infos).I'd like people to be able to write a function with any arguments that they want and still have the RPC system be able to bind to it -- adding a restriction that you have to use pointers wherever you'd normally use references would be unpreferable.e.g. Writing code that accepts a "const std::string&" is idiomatic C++, but "const std::string*" looks weird to me, unless you really need to differentiate from NULL and empty strings.   