0

hereから読むと、このC++ 11コードは私には奇妙に思えます:

template <typename Builder>
auto
makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() )
{
    auto val = builder.makeObject();
    // do stuff with val
    return val;
}

いくつか質問があります:

1) decltype(builder.makeObject()) は、実際の呼び出しが実行される前に、makeObject 関数をもう 1 回呼び出しますか?

2) そうではなく、コンパイル時にすべてがわかっている場合 (拡張マクロのようなものです)、なぜ次の構文が有効でなく、新しい戻り値の構文が必要なのですか?

//WRONG    
template <typename Builder>
    decltype( builder.makeObject() )
    makeAndProcessObject (const Builder& builder)
    {
        auto val = builder.makeObject();
        // do stuff with val
        return val;
    }

[おまけの質問 - 回答に +1 を与える] 3)この質問で、コードがコンパイルされない理由を尋ねたところ、メンバー関数 makeObject の「const」指定子が見つからないという回答がありました。答えはわかりましたが、const が必要な理由はわかりません。

次の宣言に与えるもの

template <typename Builder>
auto
makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() )

const Builder& オブジェクト参照に const makeObject または非 const makeObject がある場合は? decltype(builder.makeObject()) 部分は、関数の戻り値の型が何であるかを調べるだけで、関数がパラメーターとして渡されたオブジェクトを変更するかどうかを気にする必要はありません!

4

3 に答える 3

3

一般に、C++ のものは、宣言されるまで利用できません。あなたの例では、ビルダーが宣言される前に使用しようとしています:

template <typename Builder>
    decltype( builder.makeObject() ) // using builder here
    makeAndProcessObject (const Builder& builder) // but builder isn't declared until here
    {
        auto val = builder.makeObject();
        // do stuff with val
        return val;
    }

この問題を回避するために、関数の戻り値の型の新しい構文が追加されました。

template <typename Builder>
auto // dummy return type, meaning we will give it later
makeAndProcessObject (const Builder& builder)  // declaring builder here
-> decltype( builder.makeObject() ) // using builder here -- no problem.
{
    auto val = builder.makeObject();
    // do stuff with val
    return val;
}

おまけの質問については、 decltype に有効なパラメーターについて別のルールセットを設定するのではなく、 decltype に有効な式を指定する必要があると言語が言う方がはるかに簡単です。

于 2013-04-06T16:06:19.450 に答える
2
  1. いいえ 。 は のように未評価のコンテキストdecltypeを作成します。コンパイラは型情報だけを調べます。sizeof

  2. 先頭の戻り値の型でパラメーターを使用することはできません。

    decltype( builder.makeObject() ) makeAndProcessObject (const Builder& builder)
    

builderは不明な識別子であるため、エラーが発生します。これが、末尾の戻り値の型が作成された理由です。

  • 未評価のコンテキストでは、型情報が重要です。そして、thisパラメータがそうであるかどうかconstは、型情報の一部です。オーバーdecltypeロードの解決を行わないと、まったく役に立たなくなります。メンバー関数の -ness に基づくオーバーロードを見たことがない場合、これは意味をなさないかもしれませんがconst、同じ名前と引数を持つ 2 つの関数を持つことができます。1constつはオブジェクトのビューに対して呼び出され、もう 1 つは非const. また、戻り値の型は異なる場合があります (実際には、 a が異なることがよくありますconst)。
于 2013-04-06T16:00:34.150 に答える
1

回答:

1)いいえdecltype。コンパイル時に式の型を計算するだけで、実行時に式を評価しません。このため、decltypeはそのまま「未評価のコンテキスト」と言われsizeofnoexcept.

2) この宣言では、

template <typename Builder>
decltype( builder.makeObject() )
makeAndProcessObject (const Builder& builder)

コンパイラーはbuilder宣言を見る前にそれを見ますconst Builder& builderが、受け入れられた宣言では、戻り値の型を決定する時点で、コンパイラーは必要なすべての情報を既に解析しています。キーワードは、autoより多くの情報が利用可能になったときに戻り値の型が後で与えられることを保持するようにコンパイラーに指示します。

3)問題は宣言にありません

template <typename Builder>
auto
makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() )

それは実際には関数本体にあります。より正確には、次の行:

auto val = builder.makeObject();

builderconst Builder&唯一のconstメソッドを呼び出すことができるため、builder元々makeObject()はそれらの 1 つではありませんでした。次に、このメソッドを作成constすると問題が解決しました。

更新: Ben Voigt回答を読んだ後。上で述べたこととは反対に、関数の本体に使用したのと同じ引数がここでも適用されるため、問題は宣言にも存在します。decltype(builder.makeObject())

于 2013-04-06T16:14:07.383 に答える