2012-01-13 3 views
4

編集:私が尋ねることの最も有望なユースケースは、std::forward_as_tuple()からrvalue-referencesのタプルを受け取る関数を作成するときです。私はメンバーに彼らが右辺値、参照したかどうかを確認するために、コンストラクタの初期化子に渡されたオブジェクトのをチェックしていたので、この質問が頭に浮かんだstd :: forward_as_tuple()の結果を、そのオブジェクトのrvalue-referenceメンバーから移動できる複数の関数に渡しますか?

理由は(私はこれは間違っている間違って間違っていることを私に言ってアドバイスを開いているです...うまくいけば、これを避けるための経験則が将来的に続いていますが、それが質問を促した理由です)。わずかに異なる文脈では、私はrvalue-referenceメンバーを持つオブジェクトを複数の関数(または関数オブジェクト)に渡してしまうかもしれないということが起こりました。

template<typename... Args> 
void my_func(std::tuple<Args...>&& tup) { 

    //if tup's members are rvalue references, 
    //and this function moves guts from tup members, then... 
    func_i_dont_control(tup); 

    //what happens here if moves are done on the same members? 
    another_func_i_dont_control(std::move(tup)); 
} 

私は右辺値参照のメンバーの他のいくつかの議論とともに、Use of rvalue reference members?見てきたが、私は決定的にこれを整理するのは非常にできませんよ。

私はちょうど何が起こるかを尋ねるが、このシナリオでは、/、まったく起こり得るべきであり、右辺値参照メンバーを含むオブジェクトの周りに渡すとき、キー何のルール心に留めておくかどうかではありませんよ。

+1

あなたの例では 'tup'を送りませんか? –

+0

ええと、tup自体がテンプレート引数ではないのに、私はまだそれをしますか?私は完璧な転送でまだ少し緑色です。 –

+0

関数テンプレートパラメータとして不完全な型がある場合は、それを転送してください。 –

答えて

1

このコードでは、func_i_dont_controlは自動的にパラメータを盗むことができません。 rvaluesのみがrvalue参照にバインドされ、名前付き変数はrvalueではありません。あなたのコードがコンパイルに失敗するか、またはfunc_i_dont_control(オーバーロードがある)は移動セマンティクスを使用しません。

func_i_dont_controlにタプルを盗む(タプルを右辺値参照にバインドする)チャンスを与えるには、std::move(tup)で明示的にrvalueにキャストする必要があります。

(左辺値参照を取る関数はそれから移動してはならない、そうでなければ私たちは本当に何が起こるかわかりません。)


編集しかし、問題は、程度ではないようですタプル自体はそのメンバーです。再び、それらのメンバーは右値ではないので、func_i_dont_controlはそれらを明示的に移動する必要があります。私はそれがあなたの関数内で起こっていないrvalueとしてタプル全体を受け取らない限り、それを行う "道徳的な権利" *を持っているとは思わない。入居セマンティクスで

*あなたが一定のガイドラインに従わなければなりません。基本的には、何かを右辺値にキャストしてそれから移動することができます。左辺値または右辺値参照を扱っているかどうかは関係ありません。これらのガイドラインに従っている限り、移動セマンティクスは正しく機能します。これらのガイドラインを無視して値をキャストすると、オブジェクトは関数呼び出し後に消滅し始めます。

+0

rvalue-referenceメンバを持つオブジェクトをパラメータとして渡す(名前を付ける)のは、オブジェクトのメンバを変更することでしょうか? 'std :: forward_as_tuple()'は、その結果を受け取り、オブジェクトに名前を付ける関数に渡すとどうすれば動作しますか?私は難しくしようとしていない、私の頭はちょうどこれを釘付けにしようと回転している、笑。 –

+0

しかし、正式には、これは 'func_i_dont_control'を動かすことなく物事を混乱させる可能性があることに注意してください。原則として、 'func_i_dont_control'は後で使用するために引数へのポインタを格納することができます。これは、後に移動したオブジェクトを指します。しかし、私はそれ自体が悪いスタイルであると思います(特に、その動作を著しく記述していない悪いスタイルなので、離れる可能性のあるオブジェクトを渡さないことを知っているので、ドキュメント化されていれば、 rvalue参照引数)。 – celtschk

1

タプルと可変引数テンプレートの使用は、問題の箇所を損なうように見えるので、私はそれを修正してくださいしてみましょう。ここで起こる

void func(std::unique_ptr<Foo>&& foo) { 
    std::unique_ptr<Foo> bar1(std::move(foo)); 
    std::unique_ptr<Foo> bar2(std::move(foo)); 
} 

何?さて、bar2にはいつもヌルポインタが含まれています(の元の値に応じてbar1かもしれません)。

移動コンストラクタは正確に安全上の理由から、を必要として使用可能な状態引用にオブジェクトを残す必要があるので、何未定義の動作はありません。ですから、しかし、その状態は、おそらく非常に興味深いことではないだろう、から移動したオブジェクトを使用することができます。それも、デフォルト構築状態と等価である必要はない、それだけで古い状態とすることができます。

+1

この例は 'std :: move(foo)'なしではコンパイルできません – visitor

+0

@visitor:oups、それをキャッチしてくれてありがとう:) –

+0

オブジェクトを使用可能な状態にしておいたとき、すぐに本当に長い記事を考えましたr値参照と完璧な転送をカバーします。 [このページの下の段落(http://thbecker.net/articles/rvalue_references/section_04.html)を参照してください。 –

関連する問題