アンパサンドの有無にかかわらず関数名を使用する違いは何ですか?テンプレートパラメータにバインドされたときに、別の方法で動作することに気付きました。関数へのポインタが左辺参照にバインドできないのはなぜですか?
void foo();
template <typename F> void bind(F&);
bind(foo); // OK
bind(&foo); // Error
なぜですか?これらのケースで推測されるタイプは何ですか?
アンパサンドの有無にかかわらず関数名を使用する違いは何ですか?テンプレートパラメータにバインドされたときに、別の方法で動作することに気付きました。関数へのポインタが左辺参照にバインドできないのはなぜですか?
void foo();
template <typename F> void bind(F&);
bind(foo); // OK
bind(&foo); // Error
なぜですか?これらのケースで推測されるタイプは何ですか?
&foo
は、匿名の暫定であるため、非参照番号にバインドすることはできません。
あなたは、コンパイルが成功しているでしょう
template <typename F> void bind(const F&);
を書いていた場合。
foo
は匿名の一時的なものではないため、参照へのバインディングは許可されています。
内蔵の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
「int a;」と同じ理由があります。 void bind(int&); 'あなたは' bind(a) 'と言うことができますが、' bind(&a) 'はできません。 –