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 toT
prior to any further analysis. [...] If a prvalue initially has the type “cvT
”, whereT
is a cv-unqualified non-class, non-array type, the type of the expression is adjusted toT
prior 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 typeid
s, 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 typeid
s 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