Reputation: 35448
I have just read Is declval<T>() the same as (*(T*)nullptr)? and just realized that I haven't heard of the (*(T*)nullptr)
trick before. If I analyze that snippet, it doesn't give me too much information, beside that (quoting the answer)
you can get an instance of T in a decltype without needing to worry about T's constructor
and also the example found there is just very trivial:
struct B { A a; }; typedef decltype((*(B*)nullptr).a) T1;
so, can please someone explain to me what this (*(T*)nullptr)
trick is and why (and how) would I want to use it (beside of the example above)?
Edit: decltype(B::a)
has the same meaning (https://gcc.godbolt.org/z/Pvjjza) so why overcomplicate it like this? Are there any historical meanings to the appearance of this trick (such as some compiler not supporting it or anything else more useful?)
Upvotes: 1
Views: 194
Reputation: 32202
nullptr
is a null pointer yes!
(B*)nullptr
casts the null pointer to a pointer to an object of type B.
*(B*)nullptr
dereferences this pointer to a get a reference to an object of type B
(*(B*)nullptr).a
accesses the member 'a' of this reference.
Now if you actually executed this in a running program you may crash your program or corrupt your data or maybe nothing will happen for this is undefined behaviour. In any case it is bad and evil and should never be seen in a real program.
However if you enclose the entire expression in decltype
you get the return type of the expression rather than executing the expression.
But instead of writing the above ugliness you can use declval
. But only use declval inside a decltype
ie
typedef decltype((*(B*)nullptr).a) BMemberA;
generates you a type that is the same as the a
member of type B
. The alternative and better solution is to write.
typedef decltype(declval<B>().a) BMemberA;
Upvotes: 2