My ultimate goal is to compare the type stored within std::shared_ptr
with another type (in this testcase this type is int
)
int main() {
std::shared_ptr<int> shared_ptr_to_int;
std::cout << typeid(int).name() << std::endl;
std::cout << typeid(decltype(*shared_ptr_to_int)).name() << std::endl;
if (std::is_same<decltype(*shared_ptr_to_int), int>::value) {
std::cout << "is same!\n";
}
else {
std::cout << "not the same!\n";
}
}
For my test case I am getting the result "not the same"
.
i
i
not the same!
When "dereferencing" a std::shared_ptr
— through std::shared_ptr<...>::operator*
— the result is a reference, this means that decltype(*shared_ptr_to_int)
is equivalent to int&
.
A reference-to-int and int is not the same type, and as such you get the behavior which you are describing.
A dereferenced std::shared_ptr
yields a reference so that one can actually reach in and modify the object that the shared_ptr is currently handling.
In order to fix your example you should use std::remove_reference to strip away that (potentially unexpected) reference.
if (std::is_same<std::remove_reference<decltype(*shared_ptr_to_int)>::type, int>::value) {
...
}
You could also pass shared_ptr_to_int
as the operand of decltype and then use the result as qualifier to reach into element_type
:
if (std::is_same<decltype(shared_ptr_to_int)::element_type, int>::value) {
...
}
typeid(...).name()
return the same name for both?When typeid
is invoked with a type which is a reference it will discard this and treat the operand as if it was a non-reference type (ie. it will simply throw away the &
).
Something else worth mentioning is that the result from invoking typeid(...).name()
is implementation-defined — one should never put too much trust into the returned value. The function might even return the same name for completely distinct types — there are literally no guarantees (from the standard's point of view).
Further reading: