8

以下のメカニズムの違いを教えてください。

int function();

template<class T>
void function2(T&);

void main() {
    function2(function()); // compiler error, instantiated as int &

    const int& v = function();
    function2(v); // okay, instantiated as const int&
}

インスタンス化に関して私の推論は正しいですか? として最初にインスタンス化されないのはなぜconst T&ですか?

ありがとうございました

4

4 に答える 4

3

function非定数値を返すためです。constにできるのはオブジェクトだけです。これは、constでなければ変更できる状態が格納されているためです。そこに返されるのはオブジェクトではなく、純粋な値です。概念的には、これらは変更可能ではありませんが(たとえば、列挙定数のように)、定数修飾されていません(たとえば、列挙定数のように)。

于 2010-06-08T06:31:35.630 に答える
2

右辺値と const 修飾子の間で混乱している可能性があると思います。 functionは int 型の非 const rvalue 一時値を返すため、コンパイラは T を int であると推定します。ご指摘のとおり、一時的なものを const ref (c++03 12.2/5) にバインドできますが、コンパイラは cv 修飾子を追加して関数呼び出しを適切な形式にすることはありません。テンプレート機能を制御できないため、これを回避する方法が 2 つあります (投稿したソリューションに加えて)。

(1) 明示的なテンプレート パラメータ:function2<const int>(function())

(2) cv クオリファイ リターン:const int function();

これらのソリューションはどちらも適切に形成されています。(2)は型破りでばかげているので、(1)はより良い解決策のようです。

編集: 実際には、推定された型は ref テンプレート引数の引数よりも cv 修飾されている可能性がありますが、そうでなければ型推定が失敗する場合に限ります (c++03 14.8.2.1/3)。この場合、型推定は失敗しませんが、不正な関数呼び出しが発生します (テンプレート関数の特殊化自体は不正な形式ではないため、SFINAE は適用されません)。

テンプレート作成者の意図が引数を変更しないことであった場合、const 参照引数として宣言する必要があるため、これはテンプレート ライブラリのバグであるか、引数を変更する可能性があります。関数が引数を変更しようとしたところで失敗します。

編集: FredOverflow が指摘しているように、非クラスの右辺値は常に標準 3.10/9 によって修飾されていない cv です。gcc 4.3 で動作する (2) は、実際にはコンパイラのバグです (FredOverflow によると、gcc <4.5)。

于 2010-06-08T07:09:52.657 に答える
0

この行で

function2(function()); 

function2が戻った後、渡される引数の値が変わる可能性がありますが、function()が返され、一時変数に割り当てられるだけなので、スコープ外になった後、この一時変数はどうなるかという問題があります。コンパイラが文句を言う理由。

于 2010-06-08T05:41:22.367 に答える
0

最初の呼び出しをコンパイルするには、T &&パラメーターを使用してfunction2を定義する必要があります。これは、一時オブジェクトへの参照である右辺値です。2番目の呼び出しでは、vは左辺値の参照であり、OKです。コンパイラが右辺値参照をサポートしていない場合、最初の呼び出しは、参照なしでTパラメータを使用してのみコンパイルできます。

于 2010-06-08T05:46:36.377 に答える