Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is declval<T>() the same as (*(T*)nullptr)?

Tags:

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?

like image 826
walrii Avatar asked Feb 02 '13 00:02

walrii


1 Answers

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 a static_assert in the library:

c++/4.7/type_traits: In instantiation of '[...] std::declval() [...]': source.cpp:3:22:   required from here c++/4.7/type_traits:1776:7: error: static assertion failed: declval() must not be used! 

declval also works on reference types:

using S = int &; using T = decltype(std::declval<S>()); using U = decltype(*(S *)nullptr);  // fails 

Where the type is not a reference type, declval will give an rvalue type where nullptr gives an lvalue.

like image 192
ecatmur Avatar answered Oct 07 '22 17:10

ecatmur