Ferenc Deak
Ferenc Deak

Reputation: 35448

What is this `(*(T*)nullptr)` old trick?

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

Answers (1)

bradgonesurfing
bradgonesurfing

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

Related Questions