ベースメンバーへのポインターを作成すると、通常は派生メンバーへのポインターに変換できますが、最初のテンプレート引数が2番目の引数に影響を与える以下のBuzzのようなテンプレート内で使用する場合は変換できません。私はコンパイラのバグと戦っていますか、それとも標準はこれが機能しないことを本当に義務付けていますか?
struct Foo
{
int x;
};
struct Bar : public Foo
{
};
template<class T, int T::* z>
struct Buzz
{
};
static int Bar::* const workaround = &Foo::x;
int main()
{
// This works. Downcasting of pointer to members in general is fine.
int Bar::* y = &Foo::x;
// But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not?
// Error: could not convert template argument '&Foo::x' to 'int Bar::*'
Buzz<Bar, &Foo::x> test;
// Sun C++ 5.9 accepts this but G++ doesn't because '&' can't appear in
// a constant expression
Buzz<Bar, static_cast<int Bar::*>(&Foo::x)> test;
// Sun C++ 5.9 accepts this as well, but G++ complains "workaround cannot
// appear in a constant expression"
Buzz<Bar, workaround> test;
return 0;
}