4

この質問は、「値渡しパラメーターと noexcept を持つコンストラクター」の二重です。その質問は、値による関数引数の有効期間管理が呼び出し元の関数によって処理されることを示しました。したがって、呼び出し元は発生するすべての例外を処理し、呼び出された関数はそれ自体をマークできますnoexcept。出力端が でどのように処理されるのか疑問に思っていますnoexcept

MyType  MyFunction( SomeType const &x ) noexcept;

//...

void  MyCaller()
{
    MyType  test1 = MyFunction( RandomSomeType() );
    MyType  test2{ MyFunction( RandomSomeType() ) };
    //...
    test1 = MyFunction( RandomSomeType() );
    test2 = std::move( MyFunction(RandomSomeType()) );
    MyFunction( RandomSomeType() );  // return value goes to oblivion
}

戻り値が 内で正常に作成されたとしましょうMyFunctionMyType そして、適切な特別なメンバー関数 (copy/move-assignment/construction) が ではない可能性があるとしましょうnoexcept

  1. 呼び出された関数から呼び出し元への戻り値の転送に関する RVO/NRVO/Whatever-from-C++11 ルールnoexceptは、適切な特別なメンバー関数のステータスに関係なく、転送が常にスローなしで成功することを意味しますか?
  2. 前の質問に対する答えが「いいえ」の場合、戻り値転送がスローされる場合、例外は呼び出された関数または呼び出し元に対してカウントされますか?
  3. 前の質問に対する答えが「呼び出された関数」である場合、プレーンnoexceptマーカー onMyFunctionによって が呼び出されstd::terminateます。MyFunctionnoexceptプロファイルを何に変更する必要がありますか? Usenet でこれについて尋ねたところ、ある回答者はstd::is_nothrow_move_assignable<MyType>::value. (MyCaller戻り値を使用するいくつかの方法を使用しましたが、どの方法が使用されているかMyFunctionはわかりません! 答えはすべてのケースをカバーする必要があります。)MyTypeがコピー可能で移動不可能に変更された場合、違いはありますか?

したがって、2 番目と 3 番目の質問の最悪のケースが正確であるnoexcept場合、戻り値の型にスロー可能な動きがある場合、値によって返される関数はプレーンを持つことはできません! is_nothrow_move_assignable現在、スロー可能な移動を持つ型はまれである必要がありますが、テンプレート コードは、値による戻り値が使用されるたびに、それ自体を「ダーティ」にする必要があります。

呼び出された関数を責任あるものにするのは壊れていると思います:

MyType  MyFunction( SomeType const &x ) noexcept( ??? )
{
    //...
    try {
        return SOME_EXPRESSION;

        // What happens if the creation of SOME_EXPRESSION succeeds, but the
        // move-assignment (or whatever) transferring the result fails?  Is
        // this try/catch triggered?  Or is there no place lexically this
        // function can block a throwing move!?
    } catch (...) {
        return MyType();

        // Note that even if default-construction doesn't throw, the
        // move-assignment may throw (again)!  Now what?
    }
}

この問題は、少なくとも私には、呼び出し元の側で修正可能 (ムーブ代入をtry/でラップするだけ) のように見えcatchますが、呼び出された関数の側からは修正できません。C++ のルールを変更する必要があるとしても、呼び出し元がこれを処理する必要があると思います。または、少なくとも何らかの欠陥レポートが必要です。

4

2 に答える 2

3

あなたの質問の一部に答えるために、あなたは特定のタイプが構築可能ではないかどうか尋ねることができます:

#include <type_traits>

MyType  MyFunction( SomeType const &x )
    noexcept(std::is_nothrow_move_constructible<MyType>::value)
{
  // ....
}
于 2012-02-13T23:20:23.350 に答える