完全転送について学習するためのテスト ケースを設定しました。
std::string inner(const std::string& str ) {
return "const std::string&";
}
std::string inner(std::string& str ) {
return "std::string&";
}
std::string inner(const std::string&& str ) {
return "const std::string&&";
}
std::string inner(std::string&& str ) {
return "std::string&&";
}
template <typename T> void outer(T&& t) {
std::cout << "t: " << t << std::endl;
std::cout << "perfect forward: " << inner(std::forward<T>(t)) << std::endl;
std::cout << std::endl;
}
void PerfectForwarding()
{
outer("literal");
outer(lvalue);
outer(constlvalue);
outer(rvalue());
outer(constrvalue());
}
std::forward
期待どおりに動作します。ID なしで独自の forward 関数を実装すると、興味深い動作が現れます。
template <typename T> T&& MyForward(T& t)
{
return ((T&&)t);
}
in outer に置き換えるstd::forward
と、まったく同じ結果が得られます! MyForward
この動作は、なぜ ID が使用されるのかという疑問を投げかけます。
コンパイラ VS2010
更新 1: 型推論の防止に関して
私の知る限り、特別なタイプの控除ルールは T&& でのみアクティブになります。forward, の定義に注意してくださいforward(typename identity<T>::type& t)
。引数の型には & が 1 つだけあります。実際、ID を使用するように MyForward を変更し、(T&&) キャストを省略した後、この例はコンパイルされません。表面的には、左辺値から右辺値へのキャストにより、フォワードが機能するように見えます。
更新 2: GCC 4.5 を使用して ideone.com でテスト、同じ動作。