No, declval<T>()
is not the same as (*(T*)nullptr)
. And decltype(expr.bar)
is not the same as decltype((expr.bar))
.
The former comparison compares expressions. The latter use of decltype
inspects the expression and the former use of decltype
inspects the declared type of expr.bar
. So you have to paren your uses of the decltype
operand to make a useful comparison of the types and you will find they are different.
struct A {};
struct B {
A a;
};
// E1: B().a
// E2: declval<A>().a
// E3: (*(B*)0).a
// E4: ((B&&)(*(B*)0)).a
In these 4 expressions, all expressions have type A
. E1
is a prvalue (in C++14 it is an xvalue. Some compilers probably will treat it as an xvalue even in their C++11 mode), E2
is an xvalue. E3
is an lvalue and E4
is an xvalue again.
// T1: decltype((*(B*)0).a)
// T2: decltype(((*(B*)0).a))
In these two types, the first decltype gives the type of the member named by the expression. The member has type A
, so T1
is A
. The second decltype yields the type of the expression, modified by &
if the expression is an lvalue and modified by &&
if the expression is an xvalue. The expression is an lvalue, so T2
is A&
.