Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Constant static data member initialization

667 views
Skip to first unread message

Colin Irwin

unread,
May 21, 2003, 5:02:28 AM5/21/03
to
My question relates to the difference in how one initializes a static
const data member. For example, one can declare a class as follows:

class TestClass
{
private:
static const int dataMember__;
};

Now the data member can be (and indeed must be) initialized using one
of two methods: either in-class initialization or out of class
initialization.

In-class initialization:
------------------------
(within declaration, i.e., the header file)

class TestClass
{
private:
static const int dataMember__ = 1;
};

Out-of-class initialization:
------------------------
(in the source file)

const int TestClass::dataMember__ = 1;

What is the difference between the two methods. Obviously by having
the initialization in the header file, the distinction between
interface and implementation is lessened. Given that the value is a
constant, one may argue that it doesn't really matter.

Is this the only difference? Or am I missing something obvious (and
meaningful)?

Colin

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Francis Glassborow

unread,
May 21, 2003, 9:01:27 AM5/21/03
to
In message <99cd6250.03052...@posting.google.com>, Colin
Irwin <colin...@hotmail.com> writes

>In-class initialization:
>------------------------
>(within declaration, i.e., the header file)
>
>class TestClass
>{
> private:
> static const int dataMember__ = 1;
>};
>
>Out-of-class initialization:
>------------------------
>(in the source file)
>
>const int TestClass::dataMember__ = 1;
>
>What is the difference between the two methods. Obviously by having
>the initialization in the header file, the distinction between
>interface and implementation is lessened. Given that the value is a
>constant, one may argue that it doesn't really matter.
>
>Is this the only difference? Or am I missing something obvious (and
>meaningful)?


That the in class intialisation (note a single definition is still
required.) allows the compiler to use the value in contexts where it
cannot see the definition.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

Daniel Spangenberg

unread,
May 21, 2003, 1:10:13 PM5/21/03
to
Hello, Colin Irwin!

Colin Irwin schrieb:

> My question relates to the difference in how one initializes a static
> const data member. For example, one can declare a class as follows:
>
> class TestClass
> {
> private:
> static const int dataMember__;
> };
>
> Now the data member can be (and indeed must be) initialized using one
> of two methods: either in-class initialization or out of class
> initialization.
>
> In-class initialization:
> ------------------------
> (within declaration, i.e., the header file)
>
> class TestClass
> {
> private:
> static const int dataMember__ = 1;
> };
>
> Out-of-class initialization:
> ------------------------
> (in the source file)
>
> const int TestClass::dataMember__ = 1;
>
> What is the difference between the two methods. Obviously by having
> the initialization in the header file, the distinction between
> interface and implementation is lessened. Given that the value is a
> constant, one may argue that it doesn't really matter.
>

The very difference between these methods occurs in two cases:

1) Using the direct in-class-initialization allows the usage of the
constant in other places,
where constant integral expressions are immediatly necessary, e.g.

class TestClass
{
private:
static const int dataMember__ = 1;

double array_[dataMember__];
};


2) In cases, where the actual object of the static data member is needed
(and
not only its value), e.g. its address, you have to provide the actual
definition of
this item in the in-class case:

header:

class TestClass
{
private:
static const int dataMember__ = 1;

double array_[dataMember__];
};

translation unit:

const int TestClass::dataMember__;

Please note the missing initialization expression in the implementation
file!

Yours,

Daniel

Terje Slettebø

unread,
May 21, 2003, 8:00:32 PM5/21/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:iDbNkUNE$0y+...@robinton.demon.co.uk...

>
> (note a single definition is still required.)

Are you sure about this?

That would mean that something like BOOST_STATIC_CONSTANT (when it's
implemented as static const, rather than enum) wouldn't be guaranteed to
work.

I guess it may depend on how it's used. If you don't take its address, so
you basically use it as an rvalue, then compilers generally don't need a
definition.


Regards,

Terje

Francis Glassborow

unread,
May 22, 2003, 8:14:09 AM5/22/03
to
In message <W2Oya.7864$KF1.133908@amstwist00>, Terje Slettebř
<tsle...@chello.no.nospam> writes

>"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
>news:iDbNkUNE$0y+...@robinton.demon.co.uk...
>>
>> (note a single definition is still required.)
>
>Are you sure about this?

Yes


>
>That would mean that something like BOOST_STATIC_CONSTANT (when it's
>implemented as static const, rather than enum) wouldn't be guaranteed to
>work.
>
>I guess it may depend on how it's used. If you don't take its address, so
>you basically use it as an rvalue, then compilers generally don't need a
>definition.

In practice implementors would have to go out of their way to detect
breaches of the requirement if the address of the const is never used.
This is one of the cases where breaches are not diagnosed and we benefit
(well do not loose) from it.

I would be happy to see the standard changed to make definition
unnecessary unless the address is used but...

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

Gennaro Prota

unread,
May 27, 2003, 1:35:55 PM5/27/03
to
On 22 May 2003 08:14:09 -0400, Francis Glassborow
<francis.g...@ntlworld.com> wrote:

>In practice implementors would have to go out of their way to detect
>breaches of the requirement if the address of the const is never used.
>This is one of the cases where breaches are not diagnosed and we benefit
>(well do not loose) from it.
>
>I would be happy to see the standard changed to make definition
>unnecessary unless the address is used but...

In fact there's core DR 48 about this but I think the problem with it
is that the resolution doesn't really solve the issue in its
generality. Basically, what we wanted is, as you say, that the
definition is unnecessary unless "the address is used". That's
different (less general) than "unless it appears where an integral
constant expression is *required*", which is what the resolution
relies on. For instance:

std::string s;
...
if (s.find('a', 3) == std::string::npos) ...

To the letter of the resolution, the above requires a definition
because std::string::npos is potentially evaluated.

Fortunately, as you say, compilers behave more as we expect them to
behave than as the standard says. A further, more subtle, example that
shows this implementors' liberty is the following, taken from an old
post of mine on the boost list (for those interested... the thread is
http://news.gmane.org/onethread.php?group=gmane.comp.lib.boost.devel&root=%3C023f01c2b65a%241758e990%24cb6c6f50%40pc%3E
):

<quote>

For instance with most compilers I guess this compiles fine thanks to
the conversion to rvalue made by static_cast

struct Test
{
static const int value=1 ;
};

//const int Test::value;

void f(const int &)
{
}

int main()
{
f( static_cast<int> (Test::value) );
}


despite the fact that the expression Test::value is, as far as I
understand the standard, potentially evaluated. I think this is more a
problem in the standard than in the compilers though, because this
behavior appears natural to me.

</quote>

To summarize, the resolution to core DR 48 addresses only a part of
the problem: usage of static const members as array bounds, non-type
template arguments, etc. (all the places where you must use an
integral constant expression). It doesn't address a whole bunch of
other common uses (like the ==npos above), essentially because it
doesn't attempt to seize that intuitive concept of "the address is
taken" that we have used above.


Genny.

0 new messages