Topic: const static data members


Author: "Asif Lodhi" <asif.lodhi@gmail.com>
Date: Sun, 28 Jan 2007 18:53:36 CST
Raw View
Hi Ivan,

On 21 Jan, 10:48, Ivan Novick <i...@0x4849.net> wrote:
> I find 9.4.2/4, the paragraph describing const static data members, ........

In TC++PL 3ed, Stroustrup says, "I consider this a misfeature. When
you need a symbolic constant within a class declaration, use an
enumerator."

--
Asif

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: gennaro_prota@yahoo.com (Gennaro Prota)
Date: Mon, 22 Jan 2007 14:54:03 GMT
Raw View
On Sun, 21 Jan 2007 15:17:43 CST, James Kanze wrote:

>Of course, if the definition is required, and your program
>doesn't provide one, it is undefined behavior, not diagnostic
>required, and most, if not all, compilers will accept the last
>example without a definition.  But as far as the standard is
>concerned, it is undefined behavior.

Indeed. I solve the problem with the simple class I referred to in
reply to the OP, whose idea is by Paul Mensonides (IIRC some
volatile-related tweaks are still needed for a general purpose
facility, but it is mostly usable :-)).

The belief that no definition is needed unless you use it in an lvalue
context is so widespread that a) I was almost mocked when I suggested
to fix BOOST_STATIC_CONSTANT b) I had to fix a fix, or rather add a
comment and avoid fixing the fix (!), for the only compiler that
happened to enforce the existence of a definition:


<http://boost.cvs.sourceforge.net/boost/boost/boost/dynamic_bitset/dynamic_bitset.hpp?r1=1.11&r2=1.12>

Cassandra-ly ;-)
Genny.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "James Kanze" <james.kanze@gmail.com>
Date: Mon, 22 Jan 2007 09:36:13 CST
Raw View
James Dennett wrote:
> Francis Glassborow wrote:
> > In article <F1Dsh.21737$yC5.18740@newssvr27.news.prodigy.net>, Ivan
> > Novick <ivan@0x4849.net> writes
> >> AFAIK you don't have to define a const static int member outside of
> >> the class if it is initialized in the class.

> >> What I am missing here?

> > That you are mistaken :(
> > Yes, a compiler may miss the fact that you failed to provide a unique
> > out of class definition (because you never us the variable other than at
> > compile time) but the Standard does not condone that.

I'm not sure what Francis claims the Standard does not condone.
It certainly condones the fact that the compiler may miss the
fact that you failed to provide a declaration: "Every program
shall contain exactly one definition of every non-inline
function or object that is used in that program; no diagnostic
required."  It doesn't condone the fact that the program doesn't
provide a definition.

> True for C++98 (and C++03), but probably an oversight; the
> correction accepted for core issue 454 would make it clear
> that the definition is not required if the *value* of the
> constant is all that is used by the program.  I believe
> that this was the intent with C++98, but the wording did
> not capture the intent.

The wording has changed several times (and may still change
again before the next version of the standard).  I'd go with the
wording in C++03 until the text for the next version is more or
less stable.  (And I'm not sure about intent.  I find the
version of the text in C++98 quite clear and explicit; I've
nothing against liberalizing it, but it does represent a change
of philosophy.  And I don't see where it buys much unless the
standard also starts requiring a diagnositic if the definition
is missing.)

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "James Kanze" <james.kanze@gmail.com>
Date: Mon, 22 Jan 2007 09:35:45 CST
Raw View
Greg Herlihy wrote:
> James Kanze wrote:
> > Greg Herlihy wrote:
> > > If the static const data member
> > > appears only in its capacity as a constant integral expression, then
> > > the program does need to define the static data member outside of its
> > > class - because its object is never referenced.

> > That's sort of true.  The exact words are that the definition
> > isn't required if the value is used in a context where a
> > constant integral expression is required (or as the operand of
> > sizeof or typeof).  Thus:

> >     struct C
> >     {
> >         static int const c = 42 ;
> >     } ;
> >
> >     int array[ C::c ] ;         //  No definition required.
> >     int x = sizeof( C::c ) ;    //  No definition required.
> >     bool y = typeid( C::c ) == typeid( int ) ;
> >                                 //  No definition required.
> >     void f( int ) ;
> >
> >     void g()
> >     {
> >         f( C::c ) ;             //  Definition required.
> >     }

> No, according to    3.2/2, "C::c" in the call to f() is not "potentially
> evaluated" because the expression meets two requirements: first, C::c
> satisfies "the requirements for appearing in an integral constant
> expression"

This is a change in the latest version.  The original standard
(ISO 14882:1998) says "An expression is potentially evaluated
unless either it is the operand of the sizeof operator, or it is
the operand of the typeid operator and does not designate an
lvalue of polymorphic class type.  Earlier versions added the
qualification that I cited: "where an integral constant
expression is required".

    [...]
> And, in fact gcc, will build and link this program (unlike the sample
> program I provided) successfully - without C::c being defined outside
> of C.

As will most other compilers.  That doesn't stop it from being
undefined behavior.  (It remains undefined behavior at least
until the next version of the standard appears.)

> > Of course, if the definition is required, and your program
> > doesn't provide one, it is undefined behavior, not diagnostic
> > required, and most, if not all, compilers will accept the last
> > example without a definition.  But as far as the standard is
> > concerned, it is undefined behavior.

> > Any time the program takes the address of the object, or uses it
> > to initialize a reference, there is a high probability that the
> > compiler will complain, and refuse to compile the program, if
> > the definition is missing.  (The actual error will typically
> > only appear at link time, of course.)

> The program either needs the static data member object or it does not.

If it needs it and your code does not provide it, then the
results are undefined behavior, according to    3.2.  Even if you
pass the value by reference (which does require the definition),
a compiler might let the code through, especially if the
function is inline (and actually inlined).  Or it might not;
it's undefined behavior, so whatever the compiler does is fine.

> And unlike const global objects (and file scope static objects, both of
> which have internal linkage by default), static data members have
> external linkage - which means that the compiler cannot use a temporary
> in place of the actual static data member object to pass, say, as a
> const reference parameter.

Unless, of course, doing so has no effect on the observable
behavior of the program.

> So either the program will fail to build
> because the object is needed but not defined, or the program will build
> because the object - whether it happens to be defined or not - is not
> needed.

Whether the compiler needs the object or not is irrelevant to
the legality of the program (except insofar as it may not needed
in cases where the standard says that you're not required to
provide it).  If the standard says you have to provide it, and
you don't, it's undefined behavior.  Thus, for example, given:

    struct S
    {
        static int const  i = 42 ;
    } ;

    inline void
    f( int const& )
    {
    }

    int
    main()
    {
        f( S::i ) ;
    }

g++ (4.1.0) doesn't compile it, but Sun CC (5.8) does---both are
"right".

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Ivan Novick <ivan@0x4849.net>
Date: Sat, 20 Jan 2007 23:48:06 CST
Raw View
Hi,

I find 9.4.2/4, the paragraph describing const static data members, to
be slightly ambiguous.

"If a static data member is of const integral or const enumeration type,
its declaration can specify a const-initializer which shall be an
integral constant expression.  In that case, the member can appear in
integral constant expressions.  The member shall still be defined in a
namespace scope if it is used in the program and the namespace scope
definition shall not contain an initializer."

The last sentence has two points:

1) the member shall still be defined in a namespace scope
2) the namespace scope definition shall not contain an initializer

To me this implies that if the member is initialized in the class, the
programmer must 1) define a const static int outside the class and 2)
not initialize it outside the class.

AFAIK you don't have to define a const static int member outside of the
  class if it is initialized in the class.

What I am missing here?

Thanks,
--
Ivan
http://www.0x4849.net

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Sun, 21 Jan 2007 02:26:00 CST
Raw View
On Sat, 20 Jan 2007 23:48:06 CST, Ivan Novick wrote:

>AFAIK you don't have to define a const static int member outside of the
>  class if it is initialized in the class.
>
>What I am missing here?

You might want to look at core issue 454:

  <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#454>

A way to solve the problem in the current language is:


<http://breeze.svn.sourceforge.net/viewvc/breeze/trunk/breeze/meta/constant.hpp>


--Genny

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Sun, 21 Jan 2007 09:19:30 CST
Raw View
Ivan Novick wrote:
> I find 9.4.2/4, the paragraph describing const static data members, to
> be slightly ambiguous.
>
> "If a static data member is of const integral or const enumeration type,
> its declaration can specify a const-initializer which shall be an
> integral constant expression.  In that case, the member can appear in
> integral constant expressions.  The member shall still be defined in a
> namespace scope if it is used in the program and the namespace scope
> definition shall not contain an initializer."
>
> The last sentence has two points:
>
> 1) the member shall still be defined in a namespace scope
> 2) the namespace scope definition shall not contain an initializer
>
> To me this implies that if the member is initialized in the class, the
> programmer must 1) define a const static int outside the class and 2)
> not initialize it outside the class.

Those two points apply only if the static const object (and not just
its value) is "used" in the program. If the static const data member
appears only in its capacity as a constant integral expression, then
the program does need to define the static data member outside of its
class - because its object is never referenced.

On the other hand, consider this program:

    struct Class
    {
        static const int staticConstInt = 5;
    };

    void f( const int& p)
    {
    }

    int main()
    {
        f( Class::staticConstInt );
    }

Since f() accepts a const int by reference, the program must define
Class::staticConstInt in order to pass it as an argument to f():

    const int Class::staticConstInt;

In the interests of optimization, programs should avoid any use of a
const-declared value (whether global or static) that necessitates the
existence of a corresponding object.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sun, 21 Jan 2007 20:54:24 GMT
Raw View
In article <F1Dsh.21737$yC5.18740@newssvr27.news.prodigy.net>, Ivan
Novick <ivan@0x4849.net> writes
>AFAIK you don't have to define a const static int member outside of the
>class if it is initialized in the class.
>
>What I am missing here?

That you are mistaken :(
Yes, a compiler may miss the fact that you failed to provide a unique
out of class definition (because you never us the variable other than at
compile time) but the Standard does not condone that.


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "James Kanze" <james.kanze@gmail.com>
Date: Sun, 21 Jan 2007 15:17:43 CST
Raw View
Greg Herlihy wrote:
> Ivan Novick wrote:
> > I find 9.4.2/4, the paragraph describing const static data members, to
> > be slightly ambiguous.

> > "If a static data member is of const integral or const enumeration type,
> > its declaration can specify a const-initializer which shall be an
> > integral constant expression.  In that case, the member can appear in
> > integral constant expressions.  The member shall still be defined in a
> > namespace scope if it is used in the program and the namespace scope
> > definition shall not contain an initializer."

> > The last sentence has two points:

> > 1) the member shall still be defined in a namespace scope
> > 2) the namespace scope definition shall not contain an initializer

> > To me this implies that if the member is initialized in the class, the
> > programmer must 1) define a const static int outside the class and 2)
> > not initialize it outside the class.

> Those two points apply only if the static const object (and not just
> its value) is "used" in the program.

That's not quite true, or at least, it's not clear.  A
definition is required if the value appears in an expression
which is "potentially evaluated".

> If the static const data member
> appears only in its capacity as a constant integral expression, then
> the program does need to define the static data member outside of its
> class - because its object is never referenced.

That's sort of true.  The exact words are that the definition
isn't required if the value is used in a context where a
constant integral expression is required (or as the operand of
sizeof or typeof).  Thus:

    struct C
    {
        static int const c = 42 ;
    } ;

    int array[ C::c ] ;         //  No definition required.
    int x = sizeof( C::c ) ;    //  No definition required.
    bool y = typeid( C::c ) == typeid( int ) ;
                                //  No definition required.
    void f( int ) ;

    void g()
    {
        f( C::c ) ;             //  Definition required.
    }

Of course, if the definition is required, and your program
doesn't provide one, it is undefined behavior, not diagnostic
required, and most, if not all, compilers will accept the last
example without a definition.  But as far as the standard is
concerned, it is undefined behavior.

Any time the program takes the address of the object, or uses it
to initialize a reference, there is a high probability that the
compiler will complain, and refuse to compile the program, if
the definition is missing.  (The actual error will typically
only appear at link time, of course.)

--
James Kanze (Gabi Software)            email: james.kanze@gmail.com
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Dennett <jdennett@acm.org>
Date: Sun, 21 Jan 2007 16:26:20 CST
Raw View
Francis Glassborow wrote:
> In article <F1Dsh.21737$yC5.18740@newssvr27.news.prodigy.net>, Ivan
> Novick <ivan@0x4849.net> writes
>> AFAIK you don't have to define a const static int member outside of
>> the class if it is initialized in the class.
>>
>> What I am missing here?
>
> That you are mistaken :(
> Yes, a compiler may miss the fact that you failed to provide a unique
> out of class definition (because you never us the variable other than at
> compile time) but the Standard does not condone that.

True for C++98 (and C++03), but probably an oversight; the
correction accepted for core issue 454 would make it clear
that the definition is not required if the *value* of the
constant is all that is used by the program.  I believe
that this was the intent with C++98, but the wording did
not capture the intent.

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#454

-- James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Sun, 21 Jan 2007 23:06:31 CST
Raw View
James Kanze wrote:
> Greg Herlihy wrote:
> > If the static const data member
> > appears only in its capacity as a constant integral expression, then
> > the program does need to define the static data member outside of its
> > class - because its object is never referenced.
>
> That's sort of true.  The exact words are that the definition
> isn't required if the value is used in a context where a
> constant integral expression is required (or as the operand of
> sizeof or typeof).  Thus:
>
>     struct C
>     {
>         static int const c = 42 ;
>     } ;
>
>     int array[ C::c ] ;         //  No definition required.
>     int x = sizeof( C::c ) ;    //  No definition required.
>     bool y = typeid( C::c ) == typeid( int ) ;
>                                 //  No definition required.
>     void f( int ) ;
>
>     void g()
>     {
>         f( C::c ) ;             //  Definition required.
>     }

No, according to    3.2/2, "C::c" in the call to f() is not "potentially
evaluated" because the expression meets two requirements: first, C::c
satisfies "the requirements for appearing in an integral constant
expression" (Note specificially that the requirement is not that the
expression in which C::c appears is a constant integral expression - it
does not need to be - nor is it in this case; instead the actual
requirement is only that C::c simply be able to qualify for such an
appearance) - and second: "the lvalue-to-rvalue conversion is
immediately applied." Since C::c is being passed by value in the call
to f() - an lvalue-to-rvalue conversion does take place immediately.

And, in fact gcc, will build and link this program (unlike the sample
program I provided) successfully - without C::c being defined outside
of C.

> Of course, if the definition is required, and your program
> doesn't provide one, it is undefined behavior, not diagnostic
> required, and most, if not all, compilers will accept the last
> example without a definition.  But as far as the standard is
> concerned, it is undefined behavior.
>
> Any time the program takes the address of the object, or uses it
> to initialize a reference, there is a high probability that the
> compiler will complain, and refuse to compile the program, if
> the definition is missing.  (The actual error will typically
> only appear at link time, of course.)

The program either needs the static data member object or it does not.
And unlike const global objects (and file scope static objects, both of
which have internal linkage by default), static data members have
external linkage - which means that the compiler cannot use a temporary
in place of the actual static data member object to pass, say, as a
const reference parameter. So either the program will fail to build
because the object is needed but not defined, or the program will build
because the object - whether it happens to be defined or not - is not
needed.

Greg


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]