Defining Static Constant Elements in a Class Definition

My understanding is that C ++ allows you to define constant member members within a class if it is an integer type.

Why then does the following code give me a linker error?

#include <algorithm> #include <iostream> class test { public: static const int N = 10; }; int main() { std::cout << test::N << "\n"; std::min(9, test::N); } 

The error I get is:

 test.cpp:(.text+0x130): undefined reference to `test::N' collect2: ld returned 1 exit status 

Interestingly, if I comment on the call to std :: min, the code compiles and the links are just fine (although test :: N also refers to the previous line).

Any idea on what's going on?

My compiler is gcc 4.4 on Linux.

+94
c ++ definition static declaration
Jun 11 '10 at 20:26
source share
7 answers

My understanding is that C ++ allows you to define constant members in a class if it is an integer type.

You seem to be right. You can initialize static constant integrals in a class declaration, but this is not a definition.

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm

Interestingly, if I comment on the call to std :: min, the code compiles and the links are just fine (even if test :: N is also mentioned in the previous line).

Any idea on what's going on?

std :: min takes its parameters by reference const. If they took them at a cost, you would not have this problem, but since you need a link, you also need a definition.

Here is the chapter / verse:

9.4.2 / 4 - If a static data member is of type const integer or const enumeration, its declaration in the class definition may indicate the initializer constant, which should be an integral constant expression (5.19). In this case, the term can appear in integral constant expressions. A member still needs to be defined in the namespace area, if used in the program, and the namespace area definition should not contain an initializer .

See Chu's answer for a possible workaround.

+63
Jun 11 '10 at
source share

Bjarne Stroustrup's example in his frequently asked C ++ questions suggests that you are right and you only need a definition if you take the address.

 class AE { // ... public: static const int c6 = 7; static const int c7 = 31; }; const int AE::c7; // definition int f() { const int* p1 = &AE::c6; // error: c6 not an lvalue const int* p2 = &AE::c7; // ok // ... } 

He says, "You can take the address of a static member if (and only if) it has a definition outside the class . " This suggests that it will work differently. Perhaps your min function invokes addresses somehow behind the scenes.

+43
Jun 11 '10 at
source share

Another way to do this for integer types anyway is to define constants as enumerations in the class:

 class test { public: enum { N = 10 }; }; 
+23
Jun 11 '10 at 20:39
source share

Not just int. But you cannot define a value in a class declaration. If you have:

 class classname { public: static int const N; } 

in the .h file, then you should:

 int const classname::N = 10; 

in the .cpp file.

+10
Jun 11 '10 at 20:30
source share

Here is another way to solve the problem:

 std::min(9, int(test::N)); 

(I think Crazy Eddie answers correctly describes why the problem exists.)

+9
May 28 '11 at 7:04 AM
source share

Starting with C ++ 11 you can use:

static constexpr int N = 10;

This theoretically still requires you to define a constant in the .cpp file, but until you take the address N very unlikely that any compiler implementation will throw an error;).

+4
Sep 11 '17 at 23:38 on
source share

C ++ allows static constant members to be defined inside a class

No, 3.1 ยง2 reads:

A declaration is a definition if it does not declare a function without specifying the body of the function (8.4), contains the extern specifier (7.1.1) or the binding specification (7.5), and neither the initializer or function declares a static data member in the class definition (9.4), it a class name declaration (9.1) is an opaque-enum declaration (7.2), or it is a typedef declaration (7.1.3), a use-declaration (7.3.3), or a directive (7.3.4).

+3
Jun 11 2018-10-11T00:
source share



All Articles