¿Por qué no puedo bajar el puntero a los miembros en argumentos de plantilla?
Si hago un puntero a miembro base, puedo convertirlo en puntero a miembro derivado generalmente, pero no cuando se usa dentro de una plantilla como Buzz a continuación, donde el primer argumento de plantilla influye en el segundo. ¿Estoy luchando contra los errores del compilador o el estándar realmente exige que esto no funcione?
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;
}