C++11標準ライブラリおよびBoost.Utilityライブラリで提供されるdeclval<T>
ンプレートの戻り値型についてメモ。
template<class T> typename add_rvalue_reference<T>::type declval() noexcept;
戻り値型が単純なT&&
となっていない理由は、テンプレートパラメータT=void
型を与えたとき、ill-formedなvoid&&
ではなくvoid
に推論させるため。*1
template<class T> T&& declval() noexcept; // NG: declval<void>()がvoid&&になってしまう
C++11(N3337) 20.9.7.2 Table 53よりadd_rvalue_reference
メタ関数の定義を引用。
If
T
names an object or function type then the member typedeftype
shall nameT&&
; otherwise,type
shall nameT
. [Note: This rule reflects the semantics of reference collapsing (8.3.2). For example, when a typeT
names a typeT1&
, the typeadd_rvalue_reference<T>::type
is not an rvalue reference. -- end note]
関連URL
- c++ - Why is 'declval' specified in terms of 'add_rvalue_reference<T>::type' and not 'T&&'? - Stack Overflow
- cppreference declval, cpprefjp declval
*1:N3338 8.3.2/p1: "A declarator that specifies the type "reference to cv void" is ill-formed."