std::decay
が存在する理由は何ですか? std::decay
はどのような状況で役立ちますか?
<joke>放射性std::atomic
タイプを非放射性タイプに分解するために明らかに使用されます。</ joke>
N2609 は、std::decay
を提案した論文です。論文では次のように説明しています。
簡単に言えば、
decay<T>::type
は、Tが配列型または関数型への参照である場合を除き、ID型変換です。これらの場合、decay<T>::type
はそれぞれ、ポインターまたは関数へのポインターを生成します。
動機付けの例は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);
}
文字列リテラルを機能させるために、値でパラメータを受け入れました:
std::pair<std::string, int> p = make_pair("foo", 0);
参照によってパラメータを受け入れた場合、T1
は配列型として推定され、pair<T1, T2>
の構築は不正な形式になります。
しかし、明らかにこれは重大な非効率につながります。したがって、値渡しが発生したときに発生する一連の変換を適用するためのdecay
の必要性により、参照によってパラメーターを取得する効率を得ることができますが、コードに必要な型変換を取得することもできます文字列リテラル、配列型、関数型などを操作します。
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));
}
注:これは実際のC++ 11 make_pair
実装ではありません-C++ 11 make_pair
も展開std::reference_wrapper
s。
テンプレートタイプのパラメータを取るテンプレート関数を扱う場合、多くの場合、ユニバーサルパラメータがあります。ユニバーサルパラメーターは、ほとんどの場合、何らかの種類の参照です。また、それらはconst-volatile認定済みです。そのため、ほとんどの型特性は期待どおりに機能しません。
template<class T>
void func(T&& param) {
if (std::is_same<T,int>::value)
std::cout << "param is an int\n";
else
std::cout << "param is not an int\n";
}
int main() {
int three = 3;
func(three); //prints "param is not an int"!!!!
}
http://coliru.stacked-crooked.com/a/24476e60bd906bed
ここでの解決策は、std::decay
を使用することです。
template<class T>
void func(T&& param) {
if (std::is_same<typename std::decay<T>::type,int>::value)
std::cout << "param is an int\n";
else
std::cout << "param is not an int\n";
}