8

あなたが持っていると仮定します

  struct A{
  void f(){}
};


struct B:public A{
};


template<typename C,void (C::*f)()>
struct Call{

  void operator()(C* c){
    (c->*f)();
  }
};

なぜ

int main(){
  void (B::*f)()=&B::f;    
}

働くが

 Call<B,&B::f> a;

しません、不平を言います

could not convert template argument ‘&amp;A::f’ to ‘void (B::*)()

?

Call<A,&A::f>明らかに動作します)

似たような方法で

const void (B::*f)()=&B::f;

与える

cannot convert ‘void (A::*)()’ to ‘const void (B::*)()’ in initialization
4

2 に答える 2

4
void (B::*f)()=&B::f;   

からの暗黙的な変換のために機能します

void (A::*f)() 

void (B::*f)()

適用されます。

4.11 (2)

タイプ「タイプ cv T の B のメンバーへのポインター」の prvalue は、タイプ「タイプ cv T の D のメンバーへのポインター」の prvalue に変換できます。ここで、D は派生クラスです ( Bの第10項)

ただし、標準では、 nullptr_t 変換を除いて、テンプレート引数のメンバー関数へのポインターの変換は許可されていません。

14.3.2

メンバー関数へのポインター型の非型テンプレート パラメーターの場合、テンプレート引数が std::nullptr_t 型の場合、null メンバー ポインター変換 (4.11) が適用されます。それ以外の場合、変換は適用されません。テンプレート引数がオーバーロードされたメンバー関数のセットを表す場合、一致するメンバー関数がセットから選択されます (13.4)。

于 2012-06-21T14:03:08.783 に答える
0

エラーは何が間違っているかを正確に示してvoid (A::*)()おりvoid (B::*)()、さまざまな種類があります。

この場合は簡単に実行できるように思えますが、一般的なケースははるかに複雑になります。Aいくつかの仮想関数Bがあり、複数の継承があるとどうなるかを考えてみてください。メンバー関数へのポインターは、そのようなことを説明する必要があるため、非常に複雑な獣です。http://blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspxをご覧ください。

次のように変更できますB

struct B:public A{
    void f() { A::f(); }
};

だから、それB::f()は実際に存在します。現在、明らかにタイプであり、そうではないB::f()エイリアスですA::f()void (A::*)()void (B::*)()

于 2012-06-21T13:12:02.083 に答える