'Undefined refenence error when compiling with C++11
The example program is here:
test.h
#pragma once
#include <bitset>
class Foo{
public:
constexpr static std::bitset<9> hori1{0b111000000};
bool Bar(const std::bitset<9> cells);
};
test.cpp
#include <bitset>
#include "test.h"
bool Foo::Bar(const std::bitset<9> cells){
return hori1.any();
}
int main(){
return 0;
}
When compiling this program without the --std=c++11 everything works fine.
$ g++ -c test.cpp
$ g++ test.o
But when the flag is included, I get this:
$ g++ -c --std=c++11 test.cpp
$ g++ test.o
/usr/bin/ld: test.o: warning: relocation against `_ZN3Foo5hori1E' in read-only section `.text'
/usr/bin/ld: test.o: in function `Foo::Bar(std::bitset<9ul>)':
test.cpp:(.text+0x17): undefined reference to `Foo::hori1'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
Why is this happening only in C++11? As far as I know, test.h is correctly included and therefore hori1 should be visible from within Foo. Any help is appreciated.
Solution 1:[1]
hori1 is static. You have to define static data members in the implementation of the class.
test.cpp:
constexpr std::bitset<9> Foo::hori1;
bool Foo::Bar(const std::bitset<9> cells){
return hori1.any();
}
int main(){
return 0;
}
Solution 2:[2]
The problem is that in C++11, we have to add a corresponding definition outside the class in exactly one translation unit for a static constexpr declaration of a class' data member. This is explained in more detail below:
C++11
class Foo
{
public:
static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DECLARATION IN C++11 and C++14
//other members here
};
In the above code snippet(which is for C++11,C++14), we have a declaration of the static data member OUT_OF_BOUNDS_VALUE inside the class. And so, in exactly one translation unit we have to provide a corresponding definition. Otherwise you'll get a linker error which can be seen here.
That is, in exactly one translation unit we should write:
constexpr int Foo::OUT_OF_BOUNDS_VALUE;//note no initializer
After adding the above out of class definition with no initializer the program will work. Demo
C++17
class Foo
{
public:
static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DEFINITION IN C++17
//other members here
};
In the above code snippet(which is for C++17) we have a definition of the static data member OUT_OF_BOUNDS_VALUE inside the class. So since C++17, we don't have to provide the definition of OUT_OF_BOUNDS_VALUE anywhere else since we already have a definition for it inside the class and thus the same program works without any linker error.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | afekete |
| Solution 2 |
