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.
CodePudding user response:
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;
}
CodePudding user response:
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;//note no initializer
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.