1. ホーム
  2. c++

[解決済み] std::forwardはどのように機能するのですか?重複] [重複

2022-03-05 05:24:02

質問

重複の可能性があります。
フォワードを使用するメリット

何をするのか、どんなときに使うのか、わかってはいるけれど まだ の仕組みがよくわからないのですが。できるだけ詳しく、どのような場合に std::forward は、テンプレート引数控除を使用することが許可されている場合、不正確である。

私の混乱の一端はこれです。 もし名前があれば、それはlvalueです。 std::forward を渡すと、異なる挙動を示します。 thing&& xthing& x ?

解決方法は?

まず、このような場合、どのようにすればよいのでしょうか。 std::forward は、規格によると

§20.2.3 [forward] p2

リターンです。 static_cast<T&&>(t)

(ここで T は明示的に指定されたテンプレート・パラメータであり t は渡された引数です)。

ここで、参照の折りたたみルールを思い出してください。

TR   R

T&   &  -> T&  // lvalue reference to cv TR -> lvalue reference to T
T&   && -> T&  // rvalue reference to cv TR -> TR (lvalue reference to T)
T&&  &  -> T&  // lvalue reference to cv TR -> lvalue reference to T
T&&  && -> T&& // rvalue reference to cv TR -> TR (rvalue reference to T)

(恥ずかしながら この回答 .)

そして、完全転送を採用したいクラスを見てみましょう。

template<class T>
struct some_struct{
  T _v;
  template<class U>
  some_struct(U&& v)
    : _v(static_cast<U&&>(v)) {} // perfect forwarding here
                                 // std::forward is just syntactic sugar for this
};

そして、次に起動例を示します。

int main(){
  some_struct<int> s1(5);
  // in ctor: '5' is rvalue (int&&), so 'U' is deduced as 'int', giving 'int&&'
  // ctor after deduction: 'some_struct(int&& v)' ('U' == 'int')
  // with rvalue reference 'v' bound to rvalue '5'
  // now we 'static_cast' 'v' to 'U&&', giving 'static_cast<int&&>(v)'
  // this just turns 'v' back into an rvalue
  // (named rvalue references, 'v' in this case, are lvalues)
  // huzzah, we forwarded an rvalue to the constructor of '_v'!

  // attention, real magic happens here
  int i = 5;
  some_struct<int> s2(i);
  // in ctor: 'i' is an lvalue ('int&'), so 'U' is deduced as 'int&', giving 'int& &&'
  // applying the reference collapsing rules yields 'int&' (& + && -> &)
  // ctor after deduction and collapsing: 'some_struct(int& v)' ('U' == 'int&')
  // with lvalue reference 'v' bound to lvalue 'i'
  // now we 'static_cast' 'v' to 'U&&', giving 'static_cast<int& &&>(v)'
  // after collapsing rules: 'static_cast<int&>(v)'
  // this is a no-op, 'v' is already 'int&'
  // huzzah, we forwarded an lvalue to the constructor of '_v'!
}

このステップバイステップの回答が、あなたや他の人が、どのようにして std::forward が動作します。