Search code examples
c++gccc++11gcc4.7

C++11 Initializing class static const array


Here's what I am trying. MinGW g++ 4.7.0.

#include <iostream>
#include <string>

class Fruit
{
public:
    enum Value { APPLE, ORANGE, BANANA, NONE };
    static const Value VALUES[4] = { APPLE, ORANGE, BANANA, NONE };
    Fruit (Value v = NONE) : v_(v) { };
    std::string to_string () const {
        switch (v_) {
            case APPLE: return "apple";
            case ORANGE: return "orange";
            case BANANA: return "banana";
            default: return "none";
        }
    }
private:
    Value v_;
};

int main (int argc, char * argv[])
{
    for (Fruit f : Fruit::VALUES)
        std::cout << f.to_string() << std::endl;
    return 0;
}

I try compiling it and get the output below:

>g++ -std=c++0x test.cpp
test.cpp:9:66: error: 'constexpr' needed for in-class initialization of static d
ata member 'const Fruit::Value Fruit::VALUES [4]' of non-integral type [-fpermis
sive]


>g++ -std=c++0x -fpermissive test.cpp
test.cpp:9:66: warning: 'constexpr' needed for in-class initialization of static
 data member 'const Fruit::Value Fruit::VALUES [4]' of non-integral type [-fperm
issive]
cc1l4Xgi.o:test.cpp:(.text+0x1a): undefined reference to `Fruit::VALUES'
collect2.exe: error: ld returned 1 exit status

Is C++11 supposed to allow initializing a static const array in a class like this? Or does it have to be defined outside the class as before C++11?


Solution

  • test.cpp:9:66: error: 'constexpr' needed for in-class initialization of static d ata member 'const Fruit::Value Fruit::VALUES [4]' of non-integral type [-fpermis sive]

    Compiler told what is missing:

    class Fruit
    {
    public:
        enum Value { APPLE, ORANGE, BANANA, NONE };
        static constexpr Value VALUES[4] = { APPLE, ORANGE, BANANA, NONE };
        //     ^^^^^^^^^
    ...
    };
    

    cc1l4Xgi.o:test.cpp:(.text+0x1a): undefined reference to `Fruit::VALUES'

    To make linker happy, you must add this line somewhere in source files (not header file):

    constexpr Fruit::Value Fruit::VALUES[4];
    

    EDIT: Since c++17 we have inline variables and each constexpr variable is inline, so in C++17 the problem is solved.