1

I have a regular class, let's call it Handler, which performs some algorithm invoked on demand in runtime. The algorithm reads an array (m_arr), its content is known at compile-time so I want to utilize constexpr to initialize it.

I don't want an aggregate initializer (it might look ugly), I'd like to use a function which initializes the array. For the sake of elegance and encapsulation I want to keep them as Handler's static members. The m_arr I'd like to qualify constexpr itself, because I want to init another array with another function basing on it (if I succeed with this one in the first place).

Currently I'm struggling with four propagating errors. This is a draft of what I'm trying to achieve (with errors marked):

#include <array> class Handler { static const int SIZE = 20; static constexpr std::array<int, SIZE> initArr(); static constexpr std::array<int, SIZE> m_arr; //C2737 'private: static std::array<int, SIZE> const Handler::m_arr': 'constexpr' object must be initialized //much other non-const stuff which this class handles... }; constexpr std::array<int, Handler::SIZE> Handler::m_arr = Handler::initArr(); //C2131 expression did not evaluate to a constant constexpr std::array<int, Handler::SIZE> Handler::initArr() { std::array<int, SIZE> arr; //C3250 'arr': declaration is not allowed in 'constexpr' function body arr[0] = int(2); //C3249 illegal statement or sub-expression for 'constexpr' function arr[1] = int(7); //C3249 illegal statement or sub-expression for 'constexpr' function arr[2] = int(4); // -- || -- //... return arr; } 

Apparently I'm doing something wrong here - or - I expect from the language something which it cannot provide (compiler - MSVC 2015/14.0).

Explanation of the reason of the errors (along with a closest working alternative) very very appreciated...

11
  • Did you include<array>? Commented Oct 5, 2019 at 11:01
  • 2
    Please provide a minimal reproducible example. Show the definition of LiteralType. Commented Oct 5, 2019 at 11:01
  • @L.F. Here you have, I double-checked the error set is the same. Commented Oct 5, 2019 at 11:14
  • 1
    Shouldn't the = initArray() be part of the initial declaration? Commented Oct 5, 2019 at 11:15
  • Also, why do you think static constexpr std::array<int, SIZE> m_arr{2, 7, 4}; is ugly? Commented Oct 5, 2019 at 11:23

1 Answer 1

1

Generally speaking, static functions in classes cannot be used to initialize constexpr static data members because the function definitions are not considered at the point of initialization. You need to make it a free function and initialize the data member in the class body:

constexpr std::array<int, SIZE> init() { // ... } struct C { static constexpr std::array<int, SIZE> arr = init(); }; 
Sign up to request clarification or add additional context in comments.

4 Comments

So non-static member functions and global functions may serve as constexpr initialization measures (stackoverflow.com/questions/32803708/…) but static methods no? I'm wondering the underlying reason of that...
@bloody Static member functions aren't considered to be defined until the end of the class definition, but the initializer for the constexpr static data member is processed in the class. That's why you see a "call to undefined function" error if you make init a static function.
Assuming we have some loop-based complex initializing function (which cannot be replaced by an aggregate initializer anyway) it seems like a tangible limitation in the language (willing to contain all related stuff in the owning class). And such cases may be very common, I'm not a model but I myself do different runtime initializations (lookup tables, etc.) which otherwise might be processed as constexpr (and enclosed in a class for elegance). Wouldn't you agree with that?
@bloody Hmm ... I get your point. For now, just put the global function in a detail namespace :(

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.