Thank you and apologies to all.

I simply never looked at paragraph 1 of 5.19. I just (for some reason) jumped over it. But it says (as you state) that there is a difference between. I discovered this yesterday but didn't want to add more noise to the mailing list.

Again -- thanks and sorry...
Perry


On Feb 27, 2006, at 6:00 AM, Dave Korn wrote:

On 24 February 2006 23:42, Perry Smith wrote:

On Feb 24, 2006, at 8:55 AM, Richard Guenther wrote:

The problem is this:

struct foo {
     int a;
     int b;
     int c;
};

static const int foo::*j = &foo::c;                     // accepted

class dog {
     static const int foo::*k = &foo::c;        // error };

It has been illegal to initialise a static class member inside the class definition since sometime back in the early 90s. You must provide a static
instantiation elsewhere and initialise that.

5.19 (constant expressions) paragraph 2, the last item in the 1998 C+
+ spec says " -- a pointer to member constant expression."  That
appears to be defined as: '&' qualified-id (5.19 paragraph 6).

  Yes, the expression is a valid initialiser for the object, but the
initialiser is in a place where it is not allowed. BTW, please remember here that you have identified the expression as being a pointer-to- member constant expression, because later on you forget this fact and that's where your
confusion arises...

But '&' can occur in a constant-expression and 'foo::c' is a unique-id
which can also appear in a constant expression (see 5.19).  And as
far as the static const data member, 9.4.2 paragraph 4 says:

  This clause does not apply to /all/ static const data members...


If a static data member is of const integral or const enumeration
type,

...only ones of integral or enumeral type. And k, the static data member in
question, is a constant pointer-to-int-member-of-foo.

its declaration in the class definition can specify a
constant-initializer which shall be an integral constant expression
(5.19). In that case, the member can appear in integral constant
expressions within its scope. The member shall still be defined in
a namespace scope if it is used in the program and the namespace
scope definition shall not con- tain an initializer.

Note that 5.19 states that '&foo::c' is an integral constant
expression.

It is no such thing, and 5.19 says no such thing, and this is the point at
which you've forgotten that you already identified it as being a
pointer-to-member constant expression as defined under the terms of 5.19.6. A pointer-to-member is not any kind of integer. 5.19.2 states that it can be considered as a /constant/ expression, "only for the purpose of non- local
static object initialization".  It does not say it can be considered a
/constant integral/ expression.

And even if the initialiser expression was a constant integral expression, and we were allowed to assign it to the member, that wouldn't change the type of the member variable itself. The type of that variable is as you defined it in the class definition: it is "const int (foo::*)", and it's the type of the member variable that 9.4.2 is talking about when it says whether you can or can't initialise it in the class definition, not the type of the value with which you initialise it - closely related though those two things generally
are, they are nonetheless distinct concepts.

 So I draw the conclusion that k is a const integral
type (but I have not seen a place in the spec that actually says
that a pointer to member is an integral expression but what else
could it be?

It is a unique type of it's own, called pointer-to-member. This is a compound type, fundamentally different to integral types (and indeed to
non-member-pointer types.)

Ah. A thought has just occurred to me. You may have the misunderstanding that the static class member variable 'foo::k' is const. It isn't; the int to
which it points is const.  You can assign it to point to any other
int-member-of-foo at any time you like (and because it points to const
I-M-O-F, it's ok to assign it to point at a non-const I-M-O-F but you won't be
allowed to modify that int through it).

Is a mixup between "const int foo::*" and "int foo::* const" perhaps the root cause of your confusion? If I read the standard correctly it should be ok to initialise one of the latter in the class definition in the way you are
expecting for foo::k in your example.

    cheers,
      DaveK
--
Can't think of a witty .sigline today....



Reply via email to