4

I reduced my code to the following minimal example:

#include<array>
#include<iostream>
#include <cstdint>

enum Indices : std::uint16_t
{
    kIndex1 = 0,
    kIndex2 = 1,
    kNumIndices = 2
};

struct TestStruct
{
  static constexpr std::array<uint32_t, Indices::kNumIndices> myvals{4,7};

  template <Indices myIndex>
  static constexpr std::uint32_t GetValue()
  {
    return myvals[myIndex]*5;
  }

  static constexpr std::array<std::uint32_t, Indices::kNumIndices> newVals{GetValue<Indices::kIndex1>(), GetValue<Indices::kIndex2>()};
};

int main()
{
    auto myArr = TestStruct::newVals;
    std::cout<<myArr[Indices::kIndex1]<<"  "<<myArr[Indices::kIndex2]<<std::endl;
}

My Problem is that the code does not compile:

Test.cpp:23:97: error: ‘static constexpr uint32_t TestStruct::GetValue() [with Indices myIndex = kIndex1; uint32_t = unsigned int]’ used before its definition
   23 |   static constexpr std::array<uint32_t, Indices::kNumIndices> newVals{GetValue<Indices::kIndex1>(), GetValue<Indices::kIndex2>()};

I do not understand why it does not find the definition since it was defined above its usage.

Can you give me an explanation for this error message?

I tested also the following: When I split the struct into two structs where the second struct contains the usage of the template function in the first struct everything compiles. However, is there an another way without separating the data into two structs?

Thank you very much for your help :-)

8
  • I commented in staging ground before I realized it was staging ground. Anyway, there are options. Commented Jan 24 at 13:48
  • 1
    strange: the 3 main compilers behave differently on this one: godbolt.org/z/rdx8WGrqr Commented Jan 24 at 13:48
  • Also see stackoverflow.com/questions/16493652 and stackoverflow.com/questions/29551223 which have nice answers. (They're also duplicates of the duplicate target for this question.) Commented Jan 24 at 14:48
  • "I do not understand why it does not find the definition since it was defined above its usage." -- For an interesting twist, change return myvals[myIndex]*5; to return newVals[myIndex]*5; (and remove the function call from the initialization of newVals). The member function can access the data member even though the data member is defined beneath the function. Commented Jan 24 at 15:17
  • 1
    another fix might be to put static constexpr member functions and related static member data inside a base (implementation) class: godbolt.org/z/913EMEoqs Commented Jan 24 at 16:22

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.