Topic: Can I declare private constants?


Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/11/30
Raw View

In article <49fne0$nbl@engnews1.eng.sun.com>, clamage@Eng.Sun.COM (Steve Clamage) writes:
[..]
|> The appropriate comparison would be with
|>  extern const int X__fifty = 50;
|> which would appear in exactly one place, and
                         ^^^^^^^^^^^^^^^^^ (*)
|>  extern const int X__fifty;
|> every place else.

Sorry, I've messed it up. I meant "extern const"
instead of "const" and thought
    extern const int X__fifty = 50;
could stand in multiple translation units and would be enough.


DWP 7.1.5.1 [dcl.type.cv], 2:
>   Unless explicitly declared extern, a const object
>   does not have external linkage
>   and shall be initialized (8.5, 12.1);
                                        ^--(#)

Does this mean that it _may_ _not_ be initialized
if explicitly declared extern (like (*) sugggests)?

The DWP continues:
>   ... [can call default-ctor] otherwise if the const object is not
>   initialized with an explicit initializer the program is ill-formed.

So does the "Unless explicitly declared extern" extend beyond
the semicolon (#) up to the definition of ill-formed ?
Then the wording is missleading, at least for my english skills.
Otherwise "extern const int i;" would be ill-formed.


Ulf Schuenemann

--------------------------------------------------------------------
 ,_.   Ulf Schuenemann
#,  \  Fakultaet fuer Informatik, Technische Universitaet Muenchen, Germany.
 |   > email: schuenem@informatik.tu-muenchen.de
 v=-<  WWW:   http://hphalle2.informatik.tu-muenchen.de/~schuenem/

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/11/30
Raw View
In article imb@sunsystem5.informatik.tu-muenchen.de, schuenem@informatik.tu-muenchen.de (Ulf Schuenemann) writes:
>
>DWP 7.1.5.1 [dcl.type.cv], 2:
>>   Unless explicitly declared extern, a const object
>>   does not have external linkage
>>   and shall be initialized (8.5, 12.1);
>                                        ^--(#)
>
>Does this mean that it _may_ _not_ be initialized
>if explicitly declared extern (like (*) sugggests)?

No, that would lead to a contradiction. A const object must be
intialized, but does not have external linkage unless declared
extern. If you could not initialize an object declared extern,
you could not have any const objects with external linkage.


>The DWP continues:
>>   ... [can call default-ctor] otherwise if the const object is not
>>   initialized with an explicit initializer the program is ill-formed.
>
>So does the "Unless explicitly declared extern" extend beyond
>the semicolon (#) up to the definition of ill-formed ?
>Then the wording is missleading, at least for my english skills.
>Otherwise "extern const int i;" would be ill-formed.

Ah, well, it's hard to provide good wording for this stuff. I think the
wording is correct as it stands, however.

The first sentence says you have to have an initializer if the object is
declared const but not extern.

The second sentence says that every const object must be initialized;
it goes on to say that a default ctor will serve as an initializer.

Now suppose you declare
 extern const int x;
The first sentence doesn't require an initializer, since x has external
linkage. The second sentence just says x must be initialized. It doesn't
say it has to be initialized here. In fact, this line of code is a
declaration but is not a definition, so the initialization would appear
elsewhere.

---
Steve Clamage, stephen.clamage@eng.sun.com



---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/12/04
Raw View
In article ap2@sunsystem5.informatik.tu-muenchen.de, schuenem@informatik.tu-muenchen.de (Ulf Schuenemann) writes:
>
>In article <49lcij$i7h@engnews1.eng.sun.com>, clamage@Eng.Sun.COM (Steve Clamage) writes:
>|> Now suppose you declare
>|>  extern const int x;
>|> The first sentence doesn't require an initializer, since x has external
>|> linkage. The second sentence just says x must be initialized. It doesn't
>|> say it has to be initialized here. In fact, this line of code is a
>|> declaration but is not a definition, so the initialization would appear
>|> elsewhere.
>
>So you say the term "is initialized" does mean somewhere,
>not necessarily here. Then the same holds for "be initialized".

You are working too hard on this point. Let's assume we are talking
about declarations at file scope.

You can have only one definition for an object, and (by language definition)
initialization occurs (if at all) at the point of definition.

If you write
 const int x;
that is the (one and only) definition, and so it must have an initializer
at this point, if it is going to have one at all, and it must have one.

If you write
 extern const int x;
that is not a definition, and so the one and only definition (somewhere
in this or another translation unit) has the initializer. This line of code
is not a definition because it has external linkage, does not have an
initializer, and does not have a default constructor.

If you write
 extern const int x = 1;
that is a definition. The program cannot contain another definition of this x.
Since x has external linkage, other declarations of it may appear elsewhere.

---
Steve Clamage, stephen.clamage@eng.sun.com




---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/11/28
Raw View

In article <48su7l$4hj@engnews1.eng.sun.com>, clamage@Eng.sun.com (Steve Clamage) writes:
[..]
|> >class X
|> >{
|> >static const int fifty;
|> >...
|> >};
|> >int X::fifty = 50;
    ^^^^^^^^^^^^^^^^^  (*)
|>
|> But why not use the method that preserves the original intent of having
|> fifty be a manifest constant?
|>
|> class X {
|>  static const int fifty = 50;
|> };
|> and then in one place
|>  int X::fifty;

Coz I've to designate once and forever one file to contain this
definition and to link it whenever I use class X.

class X
{
};
const int X__fifty = 50;

It this works, why cant (*) work the same way ? The only
difference is, that X::fifty is a member and X__fifty isn't.
Besides membership X__fifty gives us what we want:
(a) use it as constant expression
(b) no need for a special implementation-file.

Why do we have to pay for membership by giving up property (b) ?
I cant see a rationale behinde it.

Ulf Schuenemann

--------------------------------------------------------------------
 ,_.   Ulf Schuenemann
#,  \  Fakultaet fuer Informatik, Technische Universitaet Muenchen, Germany.
 |   > email: schuenem@informatik.tu-muenchen.de
 v=-<  WWW:   http://hphalle2.informatik.tu-muenchen.de/~schuenem/

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/11/28
Raw View
In article 62g@sunsystem5.informatik.tu-muenchen.de, schuenem@informatik.tu-muenchen.de (Ulf Schuenemann) writes:

>|> >class X
>|> >{
>|> >static const int fifty;
>|> >};
>|> >int X::fifty = 50;
>    ^^^^^^^^^^^^^^^^^  (*)

>|> But why not use the method that preserves the original intent of having
>|> fifty be a manifest constant?
>|>
>|> class X {
>|>  static const int fifty = 50;
>|> };
>|> and then in one place
>|>  int X::fifty;

>Coz I've to designate once and forever one file to contain this
>definition and to link it whenever I use class X.

>const int X__fifty = 50;

>It this works, why cant (*) work the same way ? The only
>difference is, that X::fifty is a member and X__fifty isn't.

That isn't the only difference. X::fifty is (a single) global variable.
X__fifty is not global. It has static linkage, and there might be one in
every compilation unit.

The appropriate comparison would be with
 extern const int X__fifty = 50;
which would appear in exactly one place, and
 extern const int X__fifty;
every place else.

That said, the One-Definition Rule for inline member functions requires
that the compiler have some mechanism for ensuring exactly once copy of
things which have multiple definition points.
Example:

 header.h:
 ========
 class X {
  virtual int f() { .... }
  // there can be only one X::f() in the whole program
 };

Templates present a similar problem, since the template instantiation
code for an external function might appear in several compilation units.

Since the compiler must have such a mechanism anyway, it seems to me
that we could eliminate the requirement for a single point of
definition of static members. I don't know of any such proposal
before the C++ committee, however.
---
Steve Clamage, stephen.clamage@eng.sun.com



---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/30
Raw View
schuenem@informatik.tu-muenchen.de (Ulf Schuenemann) writes:

>clamage@Eng.sun.com (Steve Clamage) writes:
>[..]
>|> >class X
>|> >{
>|> >static const int fifty;
>|> >...
>|> >};
>|> >int X::fifty = 50;
>    ^^^^^^^^^^^^^^^^^  (*)
[...]
>class X
>{
>};
>const int X__fifty = 50;
>
>It this works, why cant (*) work the same way ? The only
>difference is, that X::fifty is a member and X__fifty isn't.

No, there is another, very signficant (from a compiler implementor's
perspective) difference -- X__fifty has internal linkage,
whereas X::fifty has external linkage.  If you take the address
of X__fifty in two different translation units, you will get
different results.  If you take the address of X::fifty in two different
translation units, you will get the same result.

--
Fergus Henderson              WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au               PGP: finger fjh@128.250.37.3
I will have little or no net access from Nov 30 until Dec 25,
so please email me a copy of any follow-ups.

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: ydanan@scir.ca
Date: 1995/11/21
Raw View
In <DGEFp4.IBC@bcstec.ca.boeing.com>,
Kevin Ingalls <ingkl900@ccmail.ca.boeing.com> writes:
>Steven wrote:
>
>>class X
>>{
>>private:
>>   const int fifty = 50;
>>};
>
>I assume that what you are really asking is "how can I accomplish this
>with legal syntax?" Given that, try this:
>
>class X
>{
> X() : fifty(50) {};
>private: // private, public, or protected actually has nothing
>  // to do with it
> const int fifty;
>};
>
>-or-
>
>class X
>{
> X();
>private:
> const int fifty;
>};
>
>X::X() : fifty(50)
>{
>}
>
I am not saying that the proposed solution is wrong, but I want to propose
a simpler solution:

class X
{
static const int fifty;
..
};
int X::fifty = 50;

Of course there is only one copy of the  constant in this example,
which is what the original example seemed to express.

[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/11/03
Raw View

|martelli@cadlab.cadlab.it (Alex Martelli) wrote:
[..]
|> Suppose the program, in various different source files, takes the address
|> &X::fifty, and saves it in int* variables; then, at some later points,
|> those variables are compared for equality of their contents.  We want
|> to ensure that such equality holds.  That the _contents_ of X::fifty
|> are defined in the header seen by each such source file has obviously
|> no relevance to this -- the _location_ of it must also be defined,
|> and, clearly, it will have to be in exactly one place to guarantee
|> the equality holds...

AFAIK there was a similas problem with the address of inline
memberfunctions. It was solved by the concept of "extern inline",
which now is also available for non-memberfunctions.
Inline memberfunctions are always "extern inline".

And there is the concept of "extern const" which guarantees that
even in different translation units the address is the same.
If you think of const static datamembers as "extern const" (analogously
to inline memberfunctions as "extern inline"), then

 struct A {
  static const int i = 1;
 }

could be treated like

 const int A__i = 1;

This would make a separate definition of A::i superflous while
still guaranteeing the equivalence of addresses (= external linkage).


Ulf Schuenemann

--------------------------------------------------------------------
 ,_.   Ulf Schuenemann
#,  \  Fakultaet fuer Informatik, Technische Universitaet Muenchen, Germany.
 |   > email: schuenem@informatik.tu-muenchen.de
 v=-<  WWW:   http://hphalle2.informatik.tu-muenchen.de/~schuenem/

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: clamage@eng.sun.com (Steve Clamage)
Date: 1995/10/26
Raw View
In article 2cn@meg.tesser.com, ralphs@tesser.com (Ralph Shnelvar) writes:
>
>I've been following this thread for a while (but not, obviously, from
>the beginning), and I don't understand why you guys aren't using the
>"enum hack" to simulate a class static constant?

You can use the enum hack, but it isn't necessary. You can now (if
your local compiler supports the change) declare a static member of
any integral type as a manifest constant:
 class Foo {
 public:
  static const unsigned short max = 1024;
  ...
 private:
  char buf[max];
 };
One advantage, not evident in this simple example, is that you can choose a
suitable type for 'max'.

The discussions have revolved around why it is, and whether it should continue
to be, necessary to provide a definition
 unsigned short Foo::max;
at namespace scope in one and only one place in the program.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Tony Cook <tony@online.tmx.com.au>
Date: 1995/10/26
Raw View
Ralph Shnelvar (ralphs@tesser.com) wrote:
: PMFJI,

: I've been following this thread for a while (but not, obviously, from
: the beginning), and I don't understand why you guys aren't using the
: "enum hack" to simulate a class static constant?

Because that's what it is, a hack.

--
        Tony Cook - tony@online.tmx.com.au
                    100237.3425@compuserve.com
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: vandevod@cs.rpi.edu (David Vandevoorde)
Date: 1995/10/26
Raw View
>>>>> "SC" == Steve Clamage <clamage@eng.sun.com> writes:
[...]
SC> You can use the enum hack, but it isn't necessary. You can now (if
SC> your local compiler supports the change) declare a static member of
SC> any integral type as a manifest constant:
[...]

Would you happen to know why it must be an ``integral type''?
I imagine uses for floating-point constants...

 Daveed

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/10/27
Raw View
In article 95Oct26140846@avs.cs.rpi.edu, vandevod@cs.rpi.edu (David Vandevoorde
) writes:
>
>>>>>> "SC" == Steve Clamage <clamage@eng.sun.com> writes:
>[...]
>SC> You can use the enum hack, but it isn't necessary. You can now (if
>SC> your local compiler supports the change) declare a static member of
>SC> any integral type as a manifest constant:
>[...]
>
>Would you happen to know why it must be an ``integral type''?
>I imagine uses for floating-point constants...

I believe it is because integral constant-expressions are a special item
in the language.  A floating-point constant-expression may consist only
of floating-point literals. For example, at file scope:

 const int two = 2; // 'two' is a constant-expression
 int k = two; // OK

 const double pi = 3.1415926535798;
 double x = pi; // error, 'pi' is not a constant-expression

So it seems to me that being able to write
 struct T { static const double e = 2.7182818285; };
doesn't give you any added capability or convenience compared to
 struct T { static const double e; };
because you must still provide a definition someplace.

We might someday revisit the restrictions on floating-point constants,
but it seems to me the rules are at least consistent.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/10/27
Raw View

In article 74i@ixnews3.ix.netcom.com, miker3@ix.netcom.com (Mike Rubenstein) writes:
>clamage@Eng.Sun.COM (Steve Clamage) wrote:

>>In article 95Oct26140846@avs.cs.rpi.edu, vandevod@cs.rpi.edu (David Vandevoorde
>>) writes:
>>>
>>>Would you happen to know why it must be an ``integral type''?
>>>I imagine uses for floating-point constants...

>>I believe it is because integral constant-expressions are a special item
>>in the language.  A floating-point constant-expression may consist only
>>of floating-point literals. For example, at file scope:
>>
>> const int two = 2; // 'two' is a constant-expression
>> int k = two; // OK
>>
>> const double pi = 3.1415926535798;
>> double x = pi; // error, 'pi' is not a constant-expression
>
>Am I confused?  I thought that initializers of non-aggregates could be
>any expressions, not just constant expressions and that
>
> double x = pi;
>
>above was legal.

Gak!  No, you are correct; I managed to confuse myself. The intialization of
x is OK in C++.

The expression
 two
is a constant-expression, but the expression
 pi
is not a constant-expression, which is the point I was trying to make.
I should have quit while I was ahead :-(
---
Steve Clamage, stephen.clamage@eng.sun.com




---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: vandevod@cs.rpi.edu (David Vandevoorde)
Date: 1995/10/21
Raw View
>>>>> "ST" == Stefan Tilkov <st@mlc-ratingen.de> writes:
ST> fjh@munta.cs.mu.OZ.AU (Fergus Henderson) writes:
[...]
>> class X
>> {
>> private:
>> static const int fifty = 50;
>> };
[...]
>> int X::fifty;

ST> This one has always puzzled me. What is the rationale behind *still*
ST> requiring that X::fifty be defined somewhere if it is initialized in
ST> the class declaration?
[...]
The ODR, I would think. If one decides to use the address of this
constant, it'd better be unique. My compiler will not complain about
the absence of that definition as long as the address of the constant
is not required (i.e., the value can be substituted direcly).

 Daveed
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: st@mlc-ratingen.de
Date: 1995/10/21
Raw View
fjh@munta.cs.mu.OZ.AU (Fergus Henderson) writes:

> However, the committee did recently decide to make this code legal:
>
>  class X
>  {
>  private:
>     static const int fifty = 50;
>  };
>
> The difference is the keyword `static'.
> Only integral static members can be initialized like this.
> Note that you still need a definition of X::fifty somewhere:
>
>  int X::fifty;

This one has always puzzled me. What is the rationale behind *still*
requiring that X::fifty be defined somewhere if it is initialized in
the class declaration?

--
Stefan Tilkov         This message is Copyright (C) 1995, Stefan Tilkov.
MLC Ratingen, Germany Redistribution by Microsoft Network, or any copying,
st@mlc-ratingen.de quoting and other uses of this message by Microsoft
   Network customers is explicitly prohibited.
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: martelli@cadlab.cadlab.it (Alex Martelli)
Date: 1995/10/22
Raw View
st@mlc-ratingen.de writes:
 ...
>> Note that you still need a definition of X::fifty somewhere:
>>
>>  int X::fifty;

>This one has always puzzled me. What is the rationale behind *still*
>requiring that X::fifty be defined somewhere if it is initialized in
>the class declaration?

Suppose the program, in various different source files, takes the address
&X::fifty, and saves it in int* variables; then, at some later points,
those variables are compared for equality of their contents.  We want
to ensure that such equality holds.  That the _contents_ of X::fifty
are defined in the header seen by each such source file has obviously
no relevance to this -- the _location_ of it must also be defined,
and, clearly, it will have to be in exactly one place to guarantee
the equality holds...


Alex
--
DISCLAIMER: these are TOTALLY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it                            Phone: +39 (51) 597313
CAD.LAB s.p.a., v. Ronzani 7/29, Casalecchio, Italia   Fax: +39 (51) 597120
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: miker3@ix.netcom.com (Mike Rubenstein)
Date: 1995/10/23
Raw View
martelli@cadlab.cadlab.it (Alex Martelli) wrote:

>st@mlc-ratingen.de writes:
> ...
>>> Note that you still need a definition of X::fifty somewhere:
>>>
>>>  int X::fifty;
>
>>This one has always puzzled me. What is the rationale behind *still*
>>requiring that X::fifty be defined somewhere if it is initialized in
>>the class declaration?
>
>Suppose the program, in various different source files, takes the address
>&X::fifty, and saves it in int* variables; then, at some later points,
>those variables are compared for equality of their contents.  We want
>to ensure that such equality holds.  That the _contents_ of X::fifty
>are defined in the header seen by each such source file has obviously
>no relevance to this -- the _location_ of it must also be defined,
>and, clearly, it will have to be in exactly one place to guarantee
>the equality holds...

Why must it be defined in only one place.  Consider

 class A
 {
   public:
     static const int c = 1;
     void f()
     {
       static const int i = 1;
       ...
     }
 }

in a header.

The compiler must create only one copy of i no matter how many
translation units include the header.  Why can't the mechanism that
does this also be used for c?

Michael M Rubenstein


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: vandevod@cs.rpi.edu (David Vandevoorde)
Date: 1995/10/12
Raw View
>>>>> "SB" == Steven Boswell <Steven_Boswell@intuit.com> writes:
SB> I put the following code into all the compilers I have access to,
SB> with different results.

SB> class X
SB> {
SB> private:
SB>    const int fifty = 50;
SB> };

My interpretation of the DWP is that is is not correct.
The grammar of (9.2 [class.mem]) allows it, but verse specifies:

 "A <member-declarator> can contain a <constant-initializer>
         only if it declares a `static' member (9.5) of integral or
  enumeration type."

This makes sense: if you always want it to be 50, why create an
instance per class. Thus, the correct version of the above should
probably be:

 class X {
     static const int fifty = 50;
 };

 // Somewhere:
 const int X::fifty;

If you really want a per-class instance, you'll need:

 struct X {
     X(): fifty(50) {}
 private:
     const int fifty;
 };

My question: why the restriction to integral and enumeration types?
(specifically, why not ``real'' types or even aggregates?)

 Daveed

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/10/12
Raw View

Steven_Boswell@intuit.com (Steven Boswell) writes:

>class X
>{
>private:
>   const int fifty = 50;
>};
[...]
>Is this declaration allowed in "standard" C++?  The discussion in the middle of
>page 110 of the Brown ARM Book seems to indicate this is OK.
>
>GNU C++ swallows it fine, of course.  God bless the GNU Project.

No, that declaration is not allowed in standard C++.  ARM page 110 is
talking about global objects only.  GNU C++ allows it as a non-standard
extension - note that `g++ -ansi -pedantic-errors' does _not_ swallow it fine.

However, the committee did recently decide to make this code legal:

 class X
 {
 private:
    static const int fifty = 50;
 };

The difference is the keyword `static'.
Only integral static members can be initialized like this.
Note that you still need a definition of X::fifty somewhere:

 int X::fifty;

This extension is a relatively recent change, and most compilers
don't support it yet.

--
Fergus Henderson             |  "Australia is the richest country in the world,
fjh@cs.mu.oz.au              |   according to a new system of measuring wealth
http://www.cs.mu.oz.au/~fjh  |   announced by the World Bank yesterday."
PGP: finger fjh@128.250.37.3 |  - Melbourne newspaper "The Age", 18 Sept 1995.


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Kevin Ingalls <ingkl900@ccmail.ca.boeing.com>
Date: 1995/10/14
Raw View
Steven wrote:

>class X
>{
>private:
>   const int fifty = 50;
>};

I assume that what you are really asking is "how can I accomplish this
with legal syntax?" Given that, try this:

class X
{
 X() : fifty(50) {};
private: // private, public, or protected actually has nothing to do with it
 const int fifty;
};

-or-

class X
{
 X();
private:
 const int fifty;
};

X::X() : fifty(50)
{
}

Hopefully, I answered your question.

Kevin Ingalls, (206)773-9404, ingkl900@ccmail.ca.boeing.com
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: thoff@symantec.com (Torsten Hoff)
Date: 1995/10/15
Raw View
The problem isn't really with the fact that the const is private. The problem
is that you cannot initialize a const in the class declaration, since no
storage is allocated for it at that point -- I believe that the GNU compiler
is in error for allowing you to do that. Of course, you also can't modify the
value of a const inside any of the class methods, such as your constructor.

However, there is a neat little workaround. You can initialize the const
*prior* to your object being instantiated -- you can verify this by printing
out the value in your constructor:

class X
{
private:
   const int fifty;

public:
   X() : fifty(50) { cout << fifty; };
};

I've never tried this for any data types other than integral ones, but since
your problem is dealing with an integer, this should suffice.


Torsten Hoff
thoff@symantec.com

(The views and opinions expressed are my own, and
should not be construed as representing those of
Symantec Corporation)


[Moderator's note: please note that this article is crossposted, and
please note that followups have been directed to comp.lang.c++.  mha]

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]