2017-01-25 7 views
4

アンパサンドの有無にかかわらず関数名を使用する違いは何ですか?テンプレートパラメータにバインドされたときに、別の方法で動作することに気付きました。関数へのポインタが左辺参照にバインドできないのはなぜですか?

void foo(); 
template <typename F> void bind(F&); 
bind(foo); // OK 
bind(&foo); // Error 

なぜですか?これらのケースで推測されるタイプは何ですか?

+2

「int a;」と同じ理由があります。 void bind(int&); 'あなたは' bind(a) 'と言うことができますが、' bind(&a) 'はできません。 –

答えて

2

&fooは、匿名の暫定であるため、非参照番号にバインドすることはできません。

あなたは、コンパイルが成功しているでしょう

template <typename F> void bind(const F&); 

を書いていた場合。


fooは匿名の一時的なものではないため、参照へのバインディングは許可されています。

4

内蔵のoperator&タイプT*を返します。そのため、&fooは、void (*)()の型を持つ関数ポインタを返すでしょう。これはprvalueであり、非constへの左辺参照にバインドすることはできません。つまり、bind()がパラメータとして期待しているものだけですが、失敗します。 bind(foo)について

、テンプレートpamareter F(すなわちvoid())正確関数型として推定され、それが動作するように、その後bindの引数の型は、void(&)()あろう。

function-to-pointer decayのため、foo&fooは同じ効果があるはずです。しかし、bind()のパラメータは、参照渡しとして宣言されていることに注意してください。 bind(foo)の場合、関数からポインタへの減衰は起こりません。そのため、引数の型は関数の参照として推測されます。一方、bind(&foo)の場合は、に渡すことができない関数ポインタprvalueを返すように、operator&が明示的に呼び出されます。

パラメータが渡し値として宣言された場合、関数からポインタへの減衰が発生すると、bind(foo)bind(&foo)は同じ効果を持ち、両方とも正常に動作します。

void foo(); 
template <typename F> void bind(F); 
bind(foo); // OK, F=void(*)() 
bind(&foo); // same as above 
関連する問題