std::forward ではテンプレート引数の推論が無効になっているのはなぜですか? 質問する

std::forward ではテンプレート引数の推論が無効になっているのはなぜですか? 質問する

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&&、テンプレート引数の推論により と推論されますTXしたがって、パラメータの型は になります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::forwardT&&7func()argstd::forwardstd::forwardT&&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));
}

おすすめ記事