2

The following code produces an undefined reference to 'Test::color'.

#include <iostream>

struct Color{
    int r,g,b;
};

void printColor(Color color) {
    //printing color
}

class Test {
    static constexpr Color color = {242,34,4};
public:
    void print(){
        printColor(color);
    }
};


int main() {
    Test test;
    test.print();

    return 0;
}

Why does this code produce the above error and what is the best way to avoid it, considering I want to use the latest version of the standard, C++17?

Should I define the static member variable, just like it was needed in earlier revisions of the standard (see the first answer here: Undefined reference to static constexpr char[]) or should I just create a new Color structure as can be seen below?

printColor(Color{color.r, color.g, color.b});

Edit: I'm using CLion on Ubuntu 16.04, which as far as I could find out, uses g++ 5.4 for compiling. I have set it to use C++17 and still get the same error. The error is only present when color is passed to a function.

user3738870
  • 1,415
  • 2
  • 12
  • 24
  • 1
    What's your compiler? That's a compiler bug if you did indeed compile your code with C++17. – Rakete1111 Sep 16 '18 at 14:47
  • I got the same error when I compiled with --std=c++14, but it worked fine with --std=c++17. I'm using gcc. – vincent Sep 16 '18 at 14:48
  • I'm using CLion with the default compiler on Ubuntu 16.04. I set the appropriate flag in my `CMakeLists.txt` : `set(CMAKE_CXX_STANDARD 17)` – user3738870 Sep 16 '18 at 14:52
  • Thanks, I think I got a little bit deceived by CLion then, because I could easily set it to use C++17, without a warning. But, as it seems, its default compiler doesn't even support it (fully..) – user3738870 Sep 16 '18 at 15:21

2 Answers2

3

This is due to the fact that, before C++17, you had to specifically define the static variable outside the class:

class Test { 
   /* ... etc etc ... */
}

const constexpr Color Test::color;

The constexpr-ness of the static member does not let you 'waive' this explicit definition requirement.

With C++17, you no longer need to define static members explicitly. They are implicitly "inline" variables, which get auto-defined at some point, and just once per binary, without you having to take care of it. See here for the long proposal of this feature.

Note that the definition must only appear in a single translation unit (so probably not in a header with class Test that gets included a lot).

einpoklum
  • 118,144
  • 57
  • 340
  • 684
2

The problem was neither with the code itself, nor with the standard being used. CLion's default compiler does not fully support C++17, so that's why it showed a strange behavior that it could compile static constexpr member variables, but only as long as they were not passed to functions.

After updating to the most recent compiler version, I was able to run the code successfully without any changes.

Thank you for all your contribution.

user3738870
  • 1,415
  • 2
  • 12
  • 24