Search code examples
c++templatesrttitype-traitsdecltype

decltype causes is_same<T, T> to fail (same type)


In the following snippet, I can cause is_same to claim that two types are distinct, even though they have the same mangled name, and this works in both GCC and clang. This only happens when I use decltype, if I use the commented out line then the compiler thinks both types are the same as expected. Is this somehow expected standard conforming behavior, or is this a bug?

#include <iostream>
#include <type_traits>
#include <typeinfo>

template <typename T, typename X>
void show(T, X)
{
    auto same = std::is_same<typename T::bar, X>::value;
    std::cout << "They are " << (same ? "the same" : "NOT the same") << std::endl;

    // the same string is always printed both times
    std::cout << typeid(typename T::bar).name() << std::endl;
    std::cout << typeid(X).name() << std::endl;
}

template <typename T>
struct Foo
{
    static constexpr struct E {} nested {};
    using bar = decltype(nested); // They are NOT the same
 //   using bar = E; // They are the same
};

int main()
{
    Foo<int> x;
    show(x, x.nested);
}

Click here to compile for yourself.


Solution

  • Because Foo::nested is constexpr, it is implicitly const. Therefore the type of Foo::nested is const E. But when x.nested is passed to show, the type decays and loses its const qualification. Consequently X is E but T::bar is const E.

    See http://coliru.stacked-crooked.com/a/1077cd1df2790423

    This also explains why using bar = E; gives a different result.