4

I want to create a constant and static integer array as a public class variable. It is neat to define it and initialize it right away. See code below for complete example.

#include <iostream>

class Foo {
public:
    constexpr static int arr[3][2] = {
            {1, 2},
            {3, 4},
            {5, 6}
    };
};

int main() {
    for (int i = 0; i < 3; i++) {
        std::cout << "Pair " << Foo::arr[i][0] << ", " << Foo::arr[i][1] << std::endl;
    }
    return 0;
}

However, compiling code above using g++ --std=c++11 test.cpp produces

/usr/bin/ld: /tmp/ccc7DFI5.o: in function `main':
test.cpp:(.text+0x2f): undefined reference to `Foo::arr'
/usr/bin/ld: test.cpp:(.text+0x55): undefined reference to `Foo::arr'
collect2: error: ld returned 1 exit status

Is this not possible in C++ ? More likely I am missing some part about C++ and its static variable initialization policy.

2
  • clang runs it gcc doesn't live godbolt.org/z/xavEde have an up vote and concider adding [language-lawyer] Follow up gcc runs it with -std=c++17 Commented Feb 28, 2021 at 19:39
  • 1
    GCC accepts it with -std=c++17. IIRC, such inline definitions of static class data members came with C++14 or C++17. Other compilers may have incorporated it earlier, as an extension. See here Commented Feb 28, 2021 at 19:46

2 Answers 2

6

Before C++17 (so C++11 and C++14) you have to add

constexpr int Foo::arr[3][2];

outside the body of class.

Sign up to request clarification or add additional context in comments.

5 Comments

This is also a solution. However, not a very neat one.
@Talos This was the standard method for static member variables until C++17 . Have you got something better in mind, for C++11 ?
@M.M initializing constant static array inside body of the class in one line
@Talos You also need the out-of-class definition, prior to C++17
@Talos, in class definition would solely work for integral values in C++11. Gcc is right here in rejecting the code for C++11. Didn't check that with a "real" Clang at home but I'd guess on GodBolt, some linkage simplifications might be persistent, forcing the array to have internal linkage there.
1

Compiler error was due to the C++11 standard.

Using C++17 standard by compiling above code using

g++ --std=c++17 test.cpp

produces no errors.

EDIT: This solution applies to C++17 and not C++11 as in my original question. For C++11 solution see accepted answer.

4 Comments

Although, despite my comment(s) on your question, it seems that the C++11 standard does support this. This cppreference page suggests that constexpr static int arr[] = { 1, 2, 3 }; (in a struct) is "OK" since C++11.
@AdrianMole It is OK since C++11, but also requires an out-of-class definition as per max66's answer. Prior to C++11 constexpr was not a keyword
The question is tagged C++11 so this solution is not applicable
@AdrianMole True... but perhaps this would be an appropriate spot for OP to edit the question to clarify that they are open to using later versions of the language

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.