Topic: Scope of static member initializers


Author: lippin@ragu.berkeley.edu (The Apathist)
Date: 2 Aug 90 21:42:22 GMT
Raw View
The counterexample Mike Lijewski proposes to my claimed problem with
the C++ definition compiles correctly on my CFront -- however, this
example does not:

(I've also reworked the example to clarify the reason that this
construction be appropriate.  Imagine a bounded integral type, with
distinguished constants for the min and max.)

class bounded {
    public:
     static const bounded min;
     static const bounded max;
    private:
     int p;
  static const int maxp;
     bounded(int x) { p = x; }
};

const int bounded::maxp=3;

const bounded bounded::min=0;
const bounded bounded::max=maxp;

My CFront declares the last line invalid, saying that maxp is not
defined.  But now the problem is not so clear-cut to me; perhaps this
implementation is wrong?

Also, I implied in the original article that aggregate initialization
is not allowed for classes.  To clarify, it is allowed for classes
that have no base classes, private or protected members, and no
virtual functions, but not otherwise.

     --Tom Lippincott
       lippin@math.berkeley.edu




Author: rfg@NCD.COM (Ron Guilmette)
Date: 4 Aug 90 02:05:47 GMT
Raw View
In article <1990Aug2.214222.14165@agate.berkeley.edu> lippin@math.berkeley.edu writes:
>const int bounded::maxp=3;
>
>const bounded bounded::min=0;
>const bounded bounded::max=maxp;
>
>My CFront declares the last line invalid, saying that maxp is not
>defined.  But now the problem is not so clear-cut to me; perhaps this
>implementation is wrong?

No. RTFM, then try:

 const bounded bounded::max=bounded::maxp;

+
+
+
+
+
+
+
+

--
// Ron Guilmette
// C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.




Author: growf@ucscb.UCSC.EDU (Purple dragons! EVERYWHERE!!!)
Date: 3 Aug 90 16:10:13 GMT
Raw View
In article <> lippin@math.berkeley.edu writes:
>const bounded bounded::max=maxp;    { maxp was a member of bounded }
>
>My CFront declares the last line invalid, saying that maxp is not
>defined.  But now the problem is not so clear-cut to me; perhaps this
>implementation is wrong?

Maybe I just haven't worked with this, but it seems to me that the
scope declarations on one side of an assignment wouldn't apply to the
other, at least not by default.  Thus, since you didn't specify that
maxp was a member of bounded, it looked in the local scope.  Did you try:
const bounded bounded::max=bounded::maxp   ?

If this isn't the way things work, it should be, in my opinion...

And if this is what you said in your message, forget this, but I don't
think it is.

==GROWF!




Author: lippin@ragu.berkeley.edu (The Apathist)
Date: 1 Aug 90 03:06:32 GMT
Raw View
My pet peeve with C++ is that (accordong to CFront and a too-close
reading of the AT&T language description) initializers for static data
members of a class are in the public scope, rather than the scope of
the class.  Thus in a situation like this:

class groupmember {
   public:
      static const groupmember zero;
      ...

Zero can only be initialized through a public constructor, and even
that constructor cannot be given any constants private to the class.

As a remedy, I propose:

1) That the initializer of a data member have access to all members of
the class.

2) That when the type of a static data member of a class is the class
itself, aggregate initialization (e.g., {0,0,0}) be allowed.

3) That when the type of a static data member of a class is the class
itself, ctor-initializers (e.g., :baseclass(17),somemember(0)) be
allowed, provided that if any members are ctor-initialized, no
aggregate initialization may follow.

Aggregate initialization of structs and classes is something I've
always found awkward (and non-robust), so I wouldn't really mind
seeing it dropped entirely in favor of ctor-initializers -- although
for the sake of the past, I suppose it must be kept.

     --Tom Lippincott
       lippin@math.berkeley.edu

   "Every action of theirs, that seems to them an act of their own free
    will, is ... in bondage to the whole course of previous history."
     --Leo Tolstoi




Author: lijewski@batcomputer.tn.cornell.edu (Mike Lijewski)
Date: 1 Aug 90 12:37:45 GMT
Raw View
In article <1990Aug1.030632.2273@agate.berkeley.edu> lippin@math.berkeley.edu writes:
>My pet peeve with C++ is that (accordong to CFront and a too-close
>reading of the AT&T language description) initializers for static data
>members of a class are in the public scope, rather than the scope of
>the class.

I don't believe the initializers for static data members of a class are
in the public scope.  Consider the following:

#include <stream.h>

class X {
  public:
  static const int i;
  static const int j;
};

const int X::i = 1;
const int X::j = i;

int main() { cout << "X::i = " << X::i << ", X::j = " << X::j; }

This compiles cleanly with cfront 2.0.  This proves that the initialization
of X::j is done in the scope of the class.  My understanding is that whenever
you define something which is prefixed with classname::, you are in the
scope of `classname'.  This is how you can define member functions outside
of the class declaration and still be within the scope of the class.

>class groupmember {
>   public:
>      static const groupmember zero;
>      ...

>Zero can only be initialized through a public constructor,

Zero can be initialized with a private constructor.  Embellishing your
class a bit we have:

#include <stream.h>

class groupmember {
    public:
    static const groupmember zero;
    void f() const { cout << "p = " << p << "\n"; }
    private:
    int p;
    groupmember() { p = 1; }
};

groupmember const groupmember::zero = groupmember();

int main() { groupmember::zero.f(); return 0; }  // will print 'p = 1'

Again, this compiles cleanly under cfront 2.0, so the initialization of
groupmember::zero is again in the scope of the class.


--
Mike Lijewski  (H)607/277-0394 (W)607/254-8686
Cornell National Supercomputer Facility
ARPA: mjlx@eagle.cnsf.cornell.edu  BITNET: mjlx@cornellf.bitnet
SMAIL:  1122 Ellis Hollow Rd. Ithaca, NY  14850




Author: bs@alice.UUCP (Bjarne Stroustrup)
Date: 1 Aug 90 12:42:49 GMT
Raw View

The initializer for a static member IS in the scope of the class
of the object being initialized. See section 8.4 of the manual
(page 150 of the ARM).

A general plea: I realize that many of you haven't yet managed to
get your hands on a copy of the AT&T 2.1 reference manual or
Ellis&Stroustrup: The Annotated C++ Reference Manual, Addison-Wesley
(commonly referred to as the ARM), but please try to remember that
this is comp.STD.c++ and try to support arguments/requests with
references to the most recent draft working document (currently
that reference manual - AT&T 2.1 and the reference manual proper
in the ARM are identical).

The point is that this would minimize confusion, especially confusion
arising from people referring to different documents as ``the manual''
and different implementations as ``the compiler.''