の存在の理由は何ですか std::decay
ですか?どのような状況でstd::decay
役立ちますか?
decay_t<decltype(...)>
何auto
が推測されるかを見るには、素晴らしい組み合わせです。
の存在の理由は何ですか std::decay
ですか?どのような状況でstd::decay
役立ちますか?
decay_t<decltype(...)>
何auto
が推測されるかを見るには、素晴らしい組み合わせです。
回答:
<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";
}
decay
非常に攻撃的です。たとえば、配列への参照に適用すると、ポインターが生成されます。通常、この種のメタプログラミングIMHOにはあまりにも積極的です。
remove_const_t< remove_reference_t<T> >
場合、カスタムメタ関数にラップされる可能性があります。