On 15 Nov 2013 at 10:51, Gavin Lambert wrote:
Well, thus far when using type_info as an index into a collection I use only its type_info* value (as this is guaranteed by the standard to be unique per type but constant across multiple invocations of typeid on the same type of object), and name() is only used to print a human readable name (via MSVC) for diagnostic purposes (since the standard does NOT guarantee that the string value be unique, unlike the pointer, it's not really suitable for use as a key -- although granted most of the time you can get away with it). It's also faster. :)
Unfortunately typeid() does NOT necessarily return the same type_info instance for some type if done across DLL or shared object boundaries. This is because the compiler generates static type_info instances only for those types where typeid() is used (with weak or selectany linkage), and the linker links them up as if they were any ordinary structure instance. That means a copy per DLL/SO. The workaround is to use the mangled type specification, and to do a string comparison to match them. That works very well, so long as you are using the same compiler. In my own code I have even dumped the mangled form to disc as an easy type identifying string id for an on-disc type database (expect more of this coming for my C++ Now 2014 presentation if it is accepted!). Due to these interop problems Antony's TypeIndex does string comparisons as well. It's the only reliable way I believe.
I think that at a minimum if RTTI is enabled then boost::type_info::name() must return exactly what std::type_info::name() would, on that platform. (This is still "least cost" since it'd just be passing the return value through without modification.)
Me personally I'd prefer name() to always return the mangled name on every platform so it's portable and consistent. Unless one is using a quirks type shim not called boost::type_info. Remember that boost::type_info is not intended to be an exact replacement for std::type_info. It is expected that Boost code using std::type_info will need "porting" to boost::type_info. Antony has provided all the necessary patches required for many Boost libraries.
It should be free to add additional methods (such as raw_name or short_name or long_name or whatever) that can do whatever, including memory allocation and returning temporary values, but as long as drop-in-replacement is a goal it can't be allowed to change the behaviour of name() itself.
Again, it's not intended to be a perfect drop in. I do see Steven's point about it accidentally becoming treated by the compiler as a perfect drop in due to type slicing. How serious that is is something I'll need to consider.
When RTTI is disabled, of course, it has more freedom in the actual returned value because the standard name() doesn't exist. But it still must be able to return a const char* that has static lifetime, because people are expecting that from the RTTI-enabled case. (In particular, it must be legal to call name() on a temporary and use the returned value as a bare const char* at any later point in the code, even once the temporary is out of scope.)
On non-MSVC compilers, merely the attempt to access or create a type_info would generally cause a compiler error if RTTI is disabled. I therefore think that in this use case boost::type_info can merrily do whatever it feels like, with any API definition it feels like including returning std::string from name(). After all, the code didn't compile at all before, so no backwards compatibility is needed here - if it compiles at all and no semantics are broken, who cares? On MSVC, typeid() works just fine as does type_info if RTTI is disabled. It's just that typeid() can no longer cope with polymorphism and the compiler warns if you try to use typeid with a polymorphic type. Here things are tougher if and only if there is Boost code written to work on MSVC with RTTI off. I don't believe there is any such code in Boost, and therefore this is also a non-issue.
If the library is intended to be an alternative implementation that is *not* a drop-in replacement, then some of these strictures could be relaxed a bit (and it shouldn't inherit from std::type_info any more).
My overwhelming concern with boost::type_info is whether the present implementation will cause surprises. Antony has already done a lot of work to remove a lot of surprises by generating warnings or static assertion failures. I need to ponder more deeply the concern about undefined behaviour during a type slicing cast vs having it act as a proxy to a const std::type_info & supplied via a constructor. It'll take me a few days to ponder this I think. The latter is not undefined behaviour, but do you actually gain anything in practice? Niall -- Currently unemployed and looking for work. Work Portfolio: http://careers.stackoverflow.com/nialldouglas/