Using C++ (gcc 4.8.3) I have 2 types (T1 and T2) which have the strange property that typeid(T1).name() and typeid(T2).name() are the same but
std::is_same<T1, T2>::value is false.
How can that be? How can I investigate further to tell what the reason might be ?
@tomislav-maric the name "m" stands for unsigned long , which happens to be typedef for std::size_t , which happens to be the typedef for std::vector<>::size_type .
The typeid operator provides a program with the ability to retrieve the actual derived type of the object referred to by a pointer or a reference. This operator, along with the dynamic_cast operator, are provided for runtime type identification (RTTI) support in C++.
typeid is an operator in C++. It is used where the dynamic type or runtime type information of an object is needed. It is included in the <typeinfo> library.
The typeid operator allows the type of an object to be determined at run time. The result of typeid is a const type_info& . The value is a reference to a type_info object that represents either the type-id or the type of the expression, depending on which form of typeid is used.
Ignoring polymorphism, typeid() gives you an object representing the static type of the expression. But there are certain elements that are ignored when it comes to expression types. From [expr]:
If an expression initially has the type “reference to
T” (8.3.2, 8.5.3), the type is adjusted toTprior to any further analysis. [...] If a prvalue initially has the type “cvT”, whereTis a cv-unqualified non-class, non-array type, the type of the expression is adjusted toTprior to any further analysis.
As a result, any types which differ only in top-level cv-qualification or reference will yield the same typeid. For instance, the types int, const int, int& volatile const int&&, etc all give you the same typeid().
Basically, your initial thought process was:
typeid(T) == typeid(U) <==> std::is_same<T, U>
But the correct equivalence is:
typeid(T) == typeid(U) <==> std::is_same<expr_type<T>, expr_type<U>>
where:
template <class T>
using expr_type = std::remove_cv_t<std::remove_reference_t<T>>;
typeid ignores all cv-qualifiers:
In all cases, cv-qualifiers are ignored by typeid (that is, typeid(T)==typeid(const T))
(ref)
This means that typeid ignores all references & and const (to name a few).
int i = 0;
const int&& j = 1;
if (typeid(i).hash_code() == typeid(j).hash_code()) //returns true
std::cout << "typeid(int) == typeid(const int&&)";
Note that to compare 2 typeids, you have to use either typeid(T).hash_code() or std::type_index(typeid(T)), because only for those 2 functions is it guaranteed that 2 same typeids will be the same. Comparing references doesn't have that guarantee for example.
There is no guarantee that the same std::type_info instance will be referred to by all evaluations of the typeid expression on the same type, although std::type_info::hash_code of those type_info objects would be identical, as would be their std::type_index.
(ref)
std::remove_reference and std::remove_cv to get the behavior you wanted.
std::remove_reference removes all references of T and std::remove_cv removes all const and volatile qualifiers. You should pass T through these functions before passing them to std::is_same, so that std::is_same only compares the underlying type (if any) of T1 and T2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With