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....