Sir Mate Sir Mate - 1 year ago 190
C++ Question

Linker error with constexpr static member variable

I would appreciate some explanation why does the following code produces the compilation error:

undefined reference to sinet::testtable'

Here is the actual code:

#define TABLE_SIZE 2000
template<class Function, std::size_t... Indices>
constexpr static auto make_array_helper(Function f, std::index_sequence<Indices...>)
-> std::array<typename std::result_of<Function(std::size_t)>::type, sizeof...(Indices)>
return {{ f(Indices)... }};

template<int N, class Function>
constexpr static auto make_array(Function f)
-> std::array<typename std::result_of<Function(std::size_t)>::type, N>
return make_array_helper(f, std::make_index_sequence<N>{});
constexpr static float fun(double x) { return (float)sin(((double)x / (double)TABLE_SIZE) * M_PI * 2.0); }

class sinet{

constexpr static auto testtable = make_array<TABLE_SIZE>(fun);

The code is supposed to fill a static array at compile time, and it does work as long as the
constexpr static array
isnt a member.

If I initialize the static member as a single float, it works , as in no linker errors. But why?

There were a lot of similar questions to this, but i could not discern an answer specific to my example.

Any help would be greatly appreciated.


Thanks to djrollins's answer, I now know that the static memeber could not be evaluated as constexpr because sin can not be either.

Which is unfortunate, as all this was for initializing a static array at compile time, but it seems that is impossible.

Answer Source

There are only a few circumstances where you can initialise a static data member inside the class definition. constexpr static members can only be initialised inside the class body if the initialiser is also fully constexpr.

Your fun function contains a call to sin which, like most of the standard maths functions, is not constexpr.

Off the top of my head I think the only other circumstance in which you can initialise static data member is if it is a const integral type e.g. const int, const bool, const char etc.

All others need to be initialised outside of the class definition. i.e:

class sinet
    constexpr static auto testable;

sinet::testable = make_array<TABLE_SIZE>(fun);

There is a good overview of the rules on cppreference.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download