2016-06-30 4 views
4

私は、以下のプログラムを持っている:それは「コール(F)」の行でコンパイルに失敗しC++ 11:なぜresult_ofが関数型をlvalue_referenceとして受け入れることができますが、関数型はlvalue_referenceとして受け入れることができないのですか?

#include<type_traits> 
#include<iostream> 
using namespace std; 
template <class F, class R = typename result_of<F()>::type> 
R call(F& f) { return f(); } 

struct S { 
    double operator()(){return 0.0;} 
}; 
int f(){return 1;} 
int main() 
{ 
    S obj; 
    call(obj);//ok 
    call(f);//error! 
    return 0; 
} 

。 "call(obj)"はOKです。

(1)別のスレッドで同様の投稿をしましたC++11 result_of deducing my function type failedしかし、ファンクションオブジェクトがなぜ機能していないのかは分かりません。

(2)これは "Rコール(F & f)"に関連するかどうかわかりません:関数型はl-値を宣言できませんか?

(3)私が知っている限り、変数/関数のような名前を持つトークンはl値と見なすべきです。そして、関数のパラメータの場合、コンパイラは関数名 "f"を関数ポインタに "崩壊"させるべきでしょうか?

(4)これは配列を崩壊して関数に渡すようなものです - 関数ポインタがl値の場合、 "call(F &f)"の何が間違っていますか?

「なぜ」が私の場合、さらに詳しい説明をするのに役立つでしょうか、どこが間違っていましたか?おかげさまで

+1

おそらく、テンプレート struct F {};と言うことはできません。 F {}; ' –

答えて

5

call(f)の問題は、関数型としてFを推測するため、関数ポインタには崩壊しないということです。代わりに、関数への参照を取得します。 F()int()()であるため、C++では有効な型ではない関数を返す関数です(関数へのポインタや関数への参照は関数には返されますが、関数ではありません)。result_of<F()>の式は無効です。

result_of<F&()>を使用するとうまくいきますが、これは呼び出し元オブジェクトの呼び出し方法がより正確なためです。 call(F& f)の内部でf()を実行し、そのコンテキストでfは左辺値なので、lvalue Fを引数なしで呼び出した結果が何であるかを尋ねる必要があります。そうでなければ、間違った答えを得ることができます。考えてみましょう:今

struct S { 
    double operator()()& {return 0.0;} 
    void operator()()&& { } 
}; 

result_of<F()>::typeあなたが望む答えではないこれ、voidです。

result_of<F&()>を使用すると正しい答えが得られ、Fが関数タイプの場合にも機能するため、call(f)も機能します。

(3)私が知っている限り、変数/関数のような名前を持つトークンは、l値と見なすべきです。そして、関数のパラメータの場合、コンパイラは関数名 "f"を関数ポインタに "崩壊"させるべきでしょうか?

いいえ、上記を参照してください。 call(F&)関数は参照によってその引数を取るため、減衰はありません。

(4)これは、配列を減衰し、関数に渡すようなものです----そして、関数ポインタは、L値可能性があり、その後、「コール(F & F)」と間違って何?

参照によっても渡すと、配列は減衰しません。

引数が減衰するようにしたい場合は、ではなくcall(F& f)と記述する必要があります。しかし、たとえそれを行ったとしても、f()の結果を得るには、result_ofを正しく使用する必要があります。ここで、fは左辺です。

関連する問題