0

Why do I get undefined reference errors to NUMBER when compiling this with gcc 4.6.3?:

g++ -std=c++0x -pipe -Wall -pedantic file.c

file.c:

#include <stdio.h>
#include <utility>

class Thing {
public:
    Thing() {
        foo(NUMBER);
        const int* p = &NUMBER;
        printf("%d\n", *p);
    }
    void foo(const int& i) {}
    static const int NUMBER = 123;
};

int main() { Thing thing; return 0; }

Error:

chetic@home:~/Documents$ g++ -std=c++0x -pipe -Wall -pedantic test.c 
/tmp/cceBY2zr.o: In function `Thing::Thing()':
statest.c:(.text._ZN5ThingC2Ev[_ZN5ThingC5Ev]+0x11): undefined reference to `Thing::NUMBER'
statest.c:(.text._ZN5ThingC2Ev[_ZN5ThingC5Ev]+0x21): undefined reference to `Thing::NUMBER'

I have been referred to #3 here: http://eel.is/c++draft/class.static.data/#3 But I was hoping somebody could explain it in simpler terms.

Why doesn't the compiler give a readable error that slaps me on my hands, or alternatively, why doesn't it treat NUMBER as a variable?

Also, why does this appear as a linker error?

Chetic
  • 127
  • 2
  • 9
  • It might be being replaced with constant propagation. – maxywb Mar 25 '15 at 15:02
  • where do you expect to get NUMBER from? I don't see a definition in file.c, what makes you think it's static? – Paul Rubel Mar 25 '15 at 15:03
  • you have to define your variable. – The Paramagnetic Croissant Mar 25 '15 at 15:04
  • 1
    This is fully explained at https://gcc.gnu.org/wiki/VerboseDiagnostics#missing_static_const_definition – Jonathan Wakely Mar 25 '15 at 15:08
  • @JonathanWakely that duplicate is slightly problematic, if you are building with `C++0x` or `C++11` the rules are different and that duplicate is quoting the pre C++11 standard. Conceptually the rules are pretty similar but it could be confusing to someone reading the quotes in the duplicate and wondering why the compiler allows more than the quote imply. – Shafik Yaghmour Mar 25 '15 at 15:24
  • @ShafikYaghmour, as explained at the GCC wiki link above, didn't the rules change post-C++11? I think it would be better to improve the answers to the duplicate to note any changes between standards, rather than have two questions. – Jonathan Wakely Mar 25 '15 at 15:34

2 Answers2

6

When you take the address or bind a reference to NUMBER:

foo(NUMBER);            // bind a reference
const int* p = &NUMBER; // taking address

you are odr-using the variable which means it require an out of line definition:

const int Thing::NUMBER ;

Quoting the cppreference from above:

Informally, an object is odr-used if its address is taken, or a reference is bound to it, and a function is odr-used if a function call to it is made or its address is taken. If an object or a function is odr-used, its definition must exist somewhere in the program; a violation of that is a link-time error.

Jonathan Wakely in a comment above provided a great reference: undefined reference to `S::a'.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
3

You have to define the static data member . For example

const int Thing::NUMBER;

Inside the class the static data member is only declared. Its definition is not required if the compiler does not need its address. However your code uses the address of the data member

const int* p = &NUMBER;

Thus the compiler has to define the constant.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335