What are the reasons for the existence of std::decay
?
In what situations is std::decay
useful?
<joke>It's obviously used to decay radioactive std::atomic
types into non-radioactive ones.</joke>
N2609 is the paper that proposed std::decay
. The paper explains:
Simply put,
decay<T>::type
is the identity type-transformation except if T is an array type or a reference to a function type. In those cases thedecay<T>::type
yields a pointer or a pointer to a function, respectively.
The motivating example is C++03 std::make_pair
:
template <class T1, class T2>
inline pair<T1,T2> make_pair(T1 x, T2 y)
{
return pair<T1,T2>(x, y);
}
which accepted its parameters by value to make string literals work:
std::pair<std::string, int> p = make_pair("foo", 0);
If it accepted its parameters by reference, then T1
will be deduced as an array type, and then constructing a pair<T1, T2>
will be ill-formed.
But obviously this leads to significant inefficiencies. Hence the need for decay
, to apply the set of transformations that occurs when pass-by-value occurs, allowing you to get the efficiency of taking the parameters by reference, but still get the type transformations needed for your code to work with string literals, array types, function types and the like:
template <class T1, class T2>
inline pair< typename decay<T1>::type, typename decay<T2>::type >
make_pair(T1&& x, T2&& y)
{
return pair< typename decay<T1>::type,
typename decay<T2>::type >(std::forward<T1>(x),
std::forward<T2>(y));
}
Note: this is not the actual C++11 make_pair
implementation - the C++11 make_pair
also unwraps std::reference_wrapper
s.