メンバーポインタに関して問題があります。次のコードは、Oracle SolarisStudio12.2のCCとcygwinGCC4.3.4の両方を使用してコンパイルできませんが、Microsoft Visual C++2010では機能します。
struct A {
int x;
};
struct B : public A {
};
template<typename T> class Bar {
public:
template<typename M> void foo(M T::*p);
};
int main(int, char *[]) {
Bar<B> bbar;
bbar.foo(&B::x);
return 0;
}
最後から2番目の行で、上記の両方のコンパイラはに一致するものを見つけることができませんBar<B>::foo(int A::*)
。式のタイプ&B::x
が実際に次のint A::*
とおりであることを確認するための簡単なテストを作成しました。
// ...
static void foo(int A::*p) {
std::cout << "A" << std::endl;
}
static void foo(int B::*p) {
std::cout << "B" << std::endl;
}
int main(int, char *[]) {
foo(&B::x); // prints "A", even on MS VC++ 2010
return 0;
}
次の回避策はGCC(Oracle CCではまだテストされていません)では機能しますが、あいまいさのためにVC++では失敗します。
template<typename T> class Bar {
public:
template<typename M> void foo(M T::*p);
template<typename M, typename _T_base> inline void foo(M _T_base::*p) {
foo(static_cast<M T::*>(p));
}
};
私の質問:どの動作が正しいですか?int A::*
どうやらVC++は、メンバー関数テンプレートへの呼び出しを満たすために、からへの暗黙のアップキャストを実行しint B::*
ますが、他の2つのコンパイラは同じことを検討するべきではありませんか?