VS2010 では、std::forward は次のように定義されています。
template<class _Ty> inline
_Ty&& forward(typename identity<_Ty>::type& _Arg)
{ // forward _Arg, given explicitly specified type parameter
return ((_Ty&&)_Arg);
}
identity
テンプレート引数の推論を無効にするためだけに使用されているようです。 この場合、意図的に無効にする意味は何でしょうか?
ベストアンサー1
型のオブジェクトへの右辺値参照を、X
型をパラメータとして受け取るテンプレート関数に渡すとT&&
、テンプレート引数の推論により と推論されますT
。X
したがって、パラメータの型は になりますX&&
。関数の引数が lvalue または const lvalue の場合、コンパイラはその型をその型の lvalue 参照または const lvalue 参照と推論します。
テンプレート引数の推論を使用する場合std::forward
:
が に正しくキャストされるのはobjects with names are lvalues
、入力引数が名前のない rvalue (または など)の場合のみです。完全転送の場合、に渡す は名前があるため lvalue です。の型は lvalue 参照または const lvalue 参照として推測されます。参照折りたたみ規則により、std ::forward の は常に lvalue 参照または const lvalue 参照として解決されます。std::forward
T&&
7
func()
arg
std::forward
std::forward
T&&
static_cast<T&&>(arg)
例:
template<typename T>
T&& forward_with_deduction(T&& obj)
{
return static_cast<T&&>(obj);
}
void test(int&){}
void test(const int&){}
void test(int&&){}
template<typename T>
void perfect_forwarder(T&& obj)
{
test(forward_with_deduction(obj));
}
int main()
{
int x;
const int& y(x);
int&& z = std::move(x);
test(forward_with_deduction(7)); // 7 is an int&&, correctly calls test(int&&)
test(forward_with_deduction(z)); // z is treated as an int&, calls test(int&)
// All the below call test(int&) or test(const int&) because in perfect_forwarder 'obj' is treated as
// an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int&
// or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what
// we want in the bottom two cases.
perfect_forwarder(x);
perfect_forwarder(y);
perfect_forwarder(std::move(x));
perfect_forwarder(std::move(y));
}