答えはすでにbilzから提供されていますが、私は説明を作成しようとします.
C++ でメンバーへのポインターを取得する場合、式の結果は、式に存在する型のメンバーへのポインターではなく、メンバーが定義されている型のメンバーへのポインターになります。つまり、メンバー関数はではなく で定義されているため、式は を&B::Key
生成します。これは §5.3.1/3 で定義されており、読みにくいですが、例が付属しています。&A::Key
Key
A
B
単項 & 演算子の結果は、そのオペランドへのポインターです。オペランドは、左辺値または修飾 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
テンプレートのインスタンス化の形式が正しくありません。テンプレートのインスタンス化にキャストを追加すると、テンプレートをインスタンス化する前に強制的に変換が行われ、変換の必要がないためインスタンス化が有効になります。