Integral const static member initialized inside a class

S

subramanian100in

In the book C++ Primer(Fourth Edition) by Stanley Lippman, the
following is mentioned in page 471(Under the subsection "Intergral
const static Members Are Special")

"When a const static data member is initialized in the class body, the
data member must still be defined outside the class definition."

Here I understand that the data member should be of integral type. But
I do not get compilation error even if I do not define the integral
const static data member outside the class. Consider the following
program named x.cpp:
#include <cstdlib>
#include <iostream>

using namespace std;

class Test
{
public:
static int get(void);
private:
static const int x = 100;
};

inline int Test::get(void)
{
return x;
}

int main()
{
cout << Test::get() << endl;

return EXIT_SUCCESS;
}

Here note that Test::x is not defined outside the class definition.

When I compile this program with g++ 3.4.3
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
the program produces the following output when run:
100

Is it a bug in the compiler not to flag the missing definition of
Test::x outside the class or what is mentioned in the 'C++ Primer'
book is wrong ? Kindly clarify.
(This question is for learning purpose only. Stroustrup has suggested
the use of enum in such situations, in his book TC++PL Third Edition
Page 249 - Section '10.4.6.2 Member Constants'. But he also mentions
in this page that an initialized static integral constant member must
still be uniquely defined somewhere and the initializer may not be
repeated.)

Thanks
V.Subramanian
 
B

Branimir Maksimovic

#include <cstdlib>
#include <iostream>

using namespace std;

class Test
{
public:
static int get(void);
private:
static const int x = 100;
};

inline int Test::get(void)
{
return x;
}
........
Is it a bug in the compiler not to flag the missing definition of
Test::x outside the class or what is mentioned in the 'C++ Primer'
book is wrong ? Kindly clarify.

I think that consts of simple types are actually never defined
in memory,rather just hard coded, unless you take address of them.
That's why you have to define it, but it is unused if you don;t
need pointer.

If that is not the case then you couldn't take address of such const.


To be honest I never took address of such const ;)

Greets
 
S

SG

In the book C++ Primer(Fourth Edition) by Stanley Lippman, the
following is mentioned in page 471(Under the subsection "Intergral
const static Members Are Special")

"When a const static data member is initialized in the class body, the
data member must still be defined outside the class definition."

Here I understand that the data member should be of integral type. But
I do not get compilation error even if I do not define the integral
const static data member outside the class.

I think the author just wanted to make clear that even if an in-class
initialization of a static const member is present, it is still only a
declaration, not a definition.

You "do not get compilation error" because the compiler is happy with
declarations alone. If you really miss a definition for something that
is needed the LINKER will complain about this (linker error, not
compilation error).

In this instance, only the value of this static const member is
accessed. The compiler already knowns the value due to the
initialization and the constness. It's a compile-time constant and
doesn't require accessing the static object at runtime. If, however,
you take the address of this member or use it as an argument for a
function call that takes a reference-to-const you need to provide a
definition for the member or else the LINKER will complain about
undefined symbols.

It's common practice in metaprogramming not to provide definitions for
those compile-time constants.

Cheers,
SG
 
E

Eric Böse-Wolf

Quoting the standard 9.4.2 recital 4:
**
If a static data member is of const integral or const enumeration type,
its declaration in the class definition can specify a constant-initializer
which shall be an constant expression (5.19). 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 programm and the
namespace scope definition shall not contain an initializer.
**

My interpretation is, that the following additional line is needed
to be "standard compliant". Might be wrong. So g++ offers the service,
that you can forget about the definition in namespace scope.

....

class Test
{
public:
static int get(void);
private:
static const int x = 100;
};

//pay attation to that line
const int Test::x;

....

Yours sincerely,

Eric
 
J

James Kanze

In the book C++ Primer(Fourth Edition) by Stanley Lippman, the
following is mentioned in page 471(Under the subsection "Intergral
const static Members Are Special")
"When a const static data member is initialized in the class body, the
data member must still be defined outside the class definition."
Here I understand that the data member should be of integral type. But
I do not get compilation error even if I do not define the integral
const static data member outside the class.

[...]
Here note that Test::x is not defined outside the class definition.
When I compile this program with g++ 3.4.3
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
the program produces the following output when run:
100
Is it a bug in the compiler not to flag the missing definition of
Test::x outside the class or what is mentioned in the 'C++ Primer'
book is wrong ? Kindly clarify.

In the general case, the lack of a definition is undefined behavior,
so
nothing the compiler does with it could be a bug. In the specific
case
of initialized static members of integral type, I think there are even
special rules which say that the definition is not required if there
is
an immediate lvalue to rvalue conversion (which is the case in your
code), so the code would be legal. (Try returning an int const&,
instead of a value. That could make a difference.)

In practice, whether I've remembered the standard correctly or not, no
compiler will require a definition in the case of an immediate lvalue
to
rvalue conversion, and most won't require a definition if there is an
lvalue to rvalue conversion in an inline function which takes a
reference (e.g. something like std::vector<int>).
 
Joined
Feb 15, 2011
Messages
1
Reaction score
0
I've just stumbled into this issue. Stroustrup's book, mentioned by the OP, says: "If (and only if) you use an initialized member in a way that requires it to be stored as an object in memory, the member must be (uniquely) defined somewhere." It doesn't say what counts as that requirement. I have some code which compiles on MSVC (2008) but does not on GCC (tested with MingW 4.5.0). So evidently they disagree on what counts. My question is, who's correct? Here is the code:

Code:
class A
{
public:
  static const int N = 1;
  enum { M };
};

void f(const int& val){}
void g(int val){}

int main(int argc, const char *argv[])
{
  f(A::N); // error on GCC, works on MSVC
  f(A::M); // works on both
  g(A::N); // works on both
  f(5); // works on both
  return 0;
}

It seems to me that since a const ref should bind to an rvalue, invoking f should not count as using A::N in a way that "requires it to be stored as an object in memory". Indeed, f(5) works fine! Any insight on this?

Thanks
Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top