Why can't I turn off the member pointer in the template arguments?

If I create a pointer element to the base, I can convert it to a pointer-to-derived member, as a rule, but not when used in a template, for example Buzz below, where the first argument of the template affects the second, I am struggling with compiler errors or Does this standard really not work?

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;
}
+5
source share
1 answer

It is simply forbidden. According to ยง14.3.2 / 5:

, - non-type. - - -, .
- - (4.5) (4.7).
- - (4.4) (4.2). - -, , . , , cv-, ( ) . - template, lvalue.
- - - -- (4.3). template ( ), (13.4).
- -, , . template , (13.4).
- - - - . template -, -- (13.4).
- - (4.4).

. , (ยง4.11/2) . ++ 0x .

+5

All Articles