移動のセマンティクスを理解していますか?

こんにちは



昨日、私は正直にC ++ 11で右辺値参照がどのように機能するかを考え出したと思いました。 私は熊手に出くわすまで考えました。



したがって、頭を伸ばして関数move_if_rrを作成することをお勧めします。 このような理解テスト:成功は、デバッグしたことがない限り、正しく機能する関数としてカウントされます。 カット中のジョブの詳細。



だから、条件。

次のコードがあるとします:

テンプレート < クラス U >

クラスコンテナ

{

Uメンバー;



公開



U Get {メンバーを返す ; }

const U Get const {メンバーを返す ; }



公開



template < クラス T > void dummy const Container < T > ; //コピー

template < class T > void dummy Container < T > && ; //移動する



公開



// Tはコンテナと互換性のあるものであることが期待されます

テンプレート < クラス T >

void Fwd T && rr

{

member = move_if_rr < T > rr.Get ;

//ダミー(std :: forward <T>(rr))

}

} ;
コンテナは 、実際のメンバータイプが不明になるように、意図的にボイラープレートで作成されています。

ダミー関数は、move_if_rrのセマンティクスを明確にするためにのみ必要です(以下)。

上記のコードには意味的な負荷はありません;すべての一致はランダムであると考えてください。



次のルールを満たす関数move_if_rrを記述する必要があります。

Container.Fwdでコメントされた前方が、moveというラベルの付いたdummyを呼び出す場合:

* move_if_rrを使用すると、メンバーフィールドのmove-assignmentが呼び出されます。

Container.Fwdでコメントされた順方向がcopyとしてマークされたdummyを呼び出す場合:

* move_if_rrを使用すると、メンバーフィールドのコピー割り当てが呼び出されます。

両方の規則は、 Container型が引数としてContainer.Fwdに渡されたことを前提としています。



コメントで決定が期待されます。



UPD1。 コードをレイアウトするには、 highlight.hohli.comを使用できます(「Habrahabrのフォントタグを使用する」をチェックする必要があります)



UPD2。 move_if_rrが何であるか理解していない人のために:

これはstd :: forwardの拡張バージョンです。std:: forwardを使用すると、1つのタイプをテンプレート引数として指定し、別のタイプをパラメーターとして指定することはできません。move_if_rrはまさにこの問題を解決します。 なんで?

あるタイプが右辺値リンクによって渡された場合、そのすべての内部コンポーネントも右辺値リンクによって渡されたと見なすことができるためです。 この特定の型がどのように渡されるかを明示的に示さず、標準の前方表記法を使用した場合、コンパイラにこれを説明する方法はここだけですか?

例:

そのような機能があったとします:
テンプレート < クラス T >

void f T && rr

{

SendData std :: forward < T > rr ;

}
そして、プログラム内で何かが変わり、複合型が入り始めました(その中の古い型はフィールドのようなものです)。 以前のように、このフィールドを転送で転送する方法は? C move_if_rrこれは次のようになります。
テンプレート < クラス T >

void f T && rr

{

SendData std :: move_if_rr < T > rr。GetSomeElement ;

}


UPD 3.条件は少し言い換えられています。 前の定式化により、コンストラクターのセマンティクスに固執することができました(Fwdの代わりに、コンストラクターが使用されました)。



UPD4。 このコードの先頭にソリューションを挿入することでソリューションを確認できます完全に正しいバージョンがここにあります。SergXのオプションもあります-mplを使用しません



All Articles