Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

decltype and is_same giving confusing results

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!
  • I'm not sure why its not resulting in value being true.
  • Could somebody please explain to me what is going on?
like image 295
Christopher Leong Avatar asked Oct 27 '25 05:10

Christopher Leong


1 Answers

Introduction

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.



Elaboration

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) {
  ...
}


Why does 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:

  • typeid operator - cppreference.com
like image 188
Filip Roséen - refp Avatar answered Oct 29 '25 19:10

Filip Roséen - refp