Reputation: 10546
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 ?
Upvotes: 19
Views: 3627
Reputation: 303337
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>>;
Upvotes: 15
Reputation: 48998
typeid
ignores all cv-qualifiers:
In all cases, cv-qualifiers are ignored by typeid (that is, typeid(T)==typeid(const T))
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.
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
.
Upvotes: 6