2

私は次のようなコードを持っています

class A
{
public:
    int Key() const;
};

class B : public A
{};

template<class T, int (T::*MemFunction)() const>
class TT
{
public:
    int Get() const               {return (m_t.*MemFunction)();}

private:
    T m_t;
};

TT<B, &B::Key> t; // Wrong, cannot convert overloaded function
                  // to int (T::*MemFunction)() (VS2010)

同様の方法で機能する理由と方法は?ありがとう

4

2 に答える 2

4

答えはすでにbilzから提供されていますが、私は説明を作成しようとします.

C++ でメンバーへのポインターを取得する場合、式の結果は、式に存在する型のメンバーへのポインターではなく、メンバーが定義されている型のメンバーへのポインターになります。つまり、メンバー関数はではなく で定義されているため、式は を&B::Key生成します。これは §5.3.1/3 で定義されており、読みにくいですが、例が付属しています。&A::KeyKeyAB

単項 & 演算子の結果は、そのオペランドへのポインターです。オペランドは、左辺値または修飾 ID でなければなりません。オペランドが、型 T を持つクラス C の非静的メンバー m を指定する修飾 ID である場合、結果の型は「型 T のクラス C のメンバーへのポインター」であり、C::m を指定する prvalue です。それ以外の場合、式の型が T の場合、結果の型は「T へのポインター」であり、指定されたオブジェクトのアドレス (1.7) または指定された関数へのポインターである prvalue です。[ 注: 特に、タイプ「cv T」のオブジェクトのアドレスは、同じ cv 修飾を持つ「cv T へのポインター」です。— 終わりの注記] [例:

struct A { int i; };
struct B : A { };
... &B::i ... // has type int A::*

— 終了例 ]

これは、テンプレートのインスタンス化が次と同等であることを意味します。

TT<B, &A::Key>

ベースのメンバーへのメンバーへのポインターは派生型へのメンバーへのポインターに変換できますが、非型非テンプレート テンプレート パラメーターの特定のケースでは、変換は許可されません。非型非テンプレート テンプレート パラメータの変換は、§14.3.2/5 で定義されており、この特定のケースについて次のように述べられています。

メンバー関数へのポインター型の非型テンプレート パラメーターの場合、テンプレート引数が std::nullptr_t 型の場合、null メンバー ポインター変換 (4.11) が適用されます。それ以外の場合、変換は適用されません。

&A::Keyを に収束できないため、int (B::*)() constテンプレートのインスタンス化の形式が正しくありません。テンプレートのインスタンス化にキャストを追加すると、テンプレートをインスタンス化する前に強制的に変換が行われ、変換の必要がないためインスタンス化が有効になります。

于 2013-01-12T05:21:32.730 に答える
1

キャストはそれを機能させる必要があります:

typedef int (B::*Key)() const;
TT<Key(&B::Key)> t;
t.Get();
于 2013-01-12T04:21:16.353 に答える