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