2

I'm trying to initialize a constexpr array using C++17 via the following:

template <size_t N>
struct CStr
{
    static constexpr std::array<int, N> getArr()
    {
        std::array<int, N> a;
        for (auto idx = 0; idx < a.size(); ++idx)
        {
            a[idx] = idx * idx;
        }
        return a;
    }
    static constexpr auto arr { getArr()};
};


int main()
{
    for (const auto &el : CStr<10>::arr)
    {
        std::cout << el << std::endl;
    }
}

However this results in the following compile error about getArr not being a constexpr function. Can someone help explain why ?

<source>: In instantiation of 'constexpr const std::array<int, 10> CStr<10>::arr':
<source>:18:27:   required from 'struct CStr<10>'
<source>:24:35:   required from here
<source>:18:39: error: 'static constexpr std::array<int, N> CStr<N>::getArr() [with long unsigned int N = 10]' called in a constant expression
   18 |     static constexpr auto arr { getArr()};
      |                                 ~~~~~~^~
<source>:9:41: note: 'static constexpr std::array<int, N> CStr<N>::getArr() [with long unsigned int N = 10]' is not usable as a 'constexpr' function because:
    9 |     static constexpr std::array<int, N> getArr()
      |                                         ^~~~~~
<source>:12:9: error: 'goto' is not a constant expression
   12 |         for (auto idx = 0; idx < a.size(); ++idx)
      |         ^~~
Compiler returned: 1   |                                         ^~~~~
11
  • 1
    You have cut off the error message, it still continues - and contains a hilarious remark about goto :D Commented Dec 31, 2020 at 11:17
  • 1
    The issue disappears when you initialize std::array<int, N> a{};. clang has a much more intelligible error message for this case :) Also, using -std=c++20 makes the error disappear. Commented Dec 31, 2020 at 11:18
  • This is probably wg21.link/p1331 Commented Dec 31, 2020 at 11:27
  • Thanks dyp! Would you mind letting us know the procedure used to locate the relevant working group paper? Commented Dec 31, 2020 at 11:35
  • 1
    I was a little confused about godbolt.org/z/GM1cEG compiling OK with gcc. However it turns out it does not compile with clang.. Likely a compiler bug w/ the former. Commented Dec 31, 2020 at 17:02

1 Answer 1

4

This is a restriction in C++ until C++20, see Permitting trivial default initialization in constexpr contexts: You have to initialize all variables inside of a constexpr function. The Standard gives the following example:

C++17

constexpr int uninit() {
  int a;                  // error: variable is uninitialized
  return a;
}

C++20

constexpr int uninit() {
  struct { int a; } s;
  return s.a;                   // error: uninitialized read of s.a
}

Note that the initialization itself is OK in C++20. Reading the indeterminate value (inside the "uninitialized" object) is not OK.


To fix your issue, initialize the array or switch to C++20:

static constexpr std::array<int, N> getArr()
{
    std::array<int, N> a{}; // now initialized!
    for (auto idx = 0; idx < a.size(); ++idx)
    {
        a[idx] = idx * idx;
    }
    return a;
}
Sign up to request clarification or add additional context in comments.

Comments

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.