2

The static class member static_member not recognised in the following code.

However, it works on older versions of the compiler. The compiler I use is based on clang.

class my_class {
  public:
    static int static_member;
};

int main() {
  my_class::static_member = 0;
}

To reproduce the error, save above file as c1.cpp and run:

VER_TAG=latest # or VER_TAG=3.1.8

docker run --rm -v $(pwd):/src emscripten/emsdk::$VER_TAG emcc /src/c1.cpp

Leads to error:

wasm-ld: error: /tmp/emscripten_temp_o3wmmq8k/c1_0.o: undefined symbol: my_class::static_member

However, if I use VER_TAG=2.0.22 (earlier release of the compiler), it works fine.

Is there anything wrong with my code? Or is it related to compiler implementation?

Sohail Si
  • 2,750
  • 2
  • 22
  • 36
  • 1
    Change it to: `int my_class::static_member = 0;` and move the definition outside main function. – Jason Apr 16 '22 at 08:52

2 Answers2

8

From static data member's definition's documentation:

The declaration inside the class body is not a definition and may declare the member to be of incomplete type (other than void), including the type in which the member is declared.

So we have to first provide an out-of class definition for the static data member as shown below:

class my_class {
  public:
    static int static_member;//this is a declaration
};
int my_class::static_member = 0;//this is a definition
int main() {
 std::cout<<my_class::static_member<<std::endl;
}

From C++17 onwards we can use inline keyword so that we'll not need an out-of-class definition for the static data member anymore:

class my_class {
  public:
    inline static int static_member = 0;  // this is a definition
};

//nothing needed here

int main() {
  std::cout<<my_class::static_member; // use the static_member here
}
Jason
  • 36,170
  • 5
  • 26
  • 60
  • 3
    Got my vote for mentioning `inline`. I tend to forget that version :-) – Ted Lyngmo Apr 16 '22 at 09:03
  • Great. I will tag @ted-lyngmo as accepted answer only because he answered earlier. Thanks for the extra education by mentioning "out-of class definition" and the new `inline` usage. – Sohail Si Apr 16 '22 at 09:04
  • 1
    @jason-liam Use of `inline` is a neat solution. Thanks for mentioning that. – Sohail Si Nov 21 '22 at 16:51
5

Is there anything wrong with my code?

Yes, your static_member doesn't have a definition.

class my_class {
  public:
    static int static_member;  // declaration
};

int my_class::static_member{}; // missing definition

int main() {
  my_class::static_member = 0; // now you can use it here
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Excellent. So, how was it working before? Is it a new requirement in recent updates of C++? – Sohail Si Apr 16 '22 at 08:55
  • 2
    @SohailSi I think your older linker had a flaw that didn't detect this missing definition - or perhaps the compiler somehow added a definition by itself for some reason. – Ted Lyngmo Apr 16 '22 at 08:56
  • Not sure which one to choose as the chosen answer: Your last comment is great: it explained the "cause" of the problem (and confusion). The other answer gave the "solution" for the problem (`inline`). – Sohail Si Nov 21 '22 at 16:56
  • @SohailSi Yes, `inline` is one way to solve it from C++17. Prior to C++17, you had to do it like I showed in my answer (which still works btw). – Ted Lyngmo Nov 21 '22 at 17:01