Is declval<T>() just a replacement for the old trick of (*(T*)NULL) to get an instance of T in a decltype without needing to worry about T’s constructor?
Here is some sample code:
struct A {};
struct B {
A a;
};
typedef decltype((*(B*)nullptr).a) T1;
typedef decltype(declval<B>().a) T2;
cout << "is_same: " << is_same<T1, T2>::value << endl;
which prints 1 because T1 and T2 are the same type.
If declval is more than a replacement, what are the differences and where is it useful?
declval()has the advantage that if it is used in an evaluated context (i.e., odr-used) then the program is ill-formed (20.2.4p2), and a diagnostic is required to be issued (per 1.4p1). Typically this is enforced through astatic_assertin the library:declvalalso works on reference types:Where the type is not a reference type,
declvalwill give an rvalue type wherenullptrgives an lvalue.