1

I am trying to statically initialize a constexpr std::array of objects containing function pointers with the following code:

#include <array>

using TVoidVoid = void(*)(void);

class State{
public:
  constexpr State(TVoidVoid function) : function_{function}{}
private:
  TVoidVoid function_;
};

void OnEvent1(){}
void OnEvent2(){}
constexpr std::array<State, 10> states = {{OnEvent1}, {OnEvent2}};

int main(){}

I am compiling with:

g++ -Wall -Wextra -Wshadow -Weffc++ -Wstrict-aliasing -ansi -pedantic -Werror -std=c++14 main.cpp

I have trouble understanding the compiling error I'm getting:

main.cpp:14:69: error: too many initializers for ‘const std::array<State, 10>’
 constexpr std::array<State, 10> states = {{OnEvent1}, {OnEvent2}}

The compiler is g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0.

What could be the problem here? Many thanks in advance!

2 Answers 2

2

The error message could be better. But what's tripping the initialization is in fact that you don't have enough braces. Recall that a std::array is an aggregate wrapping a raw array. So you need to initialize like this:

constexpr std::array<State, 10> states = {{ {OnEvent1}, {OnEvent2} }};

Otherwise, the somewhat inaccurate brace ellision detection algorithm assumes {OnEvent1} is to initialize the internal array, and the second clause is redundant.

Now you just need to provide a default c'tor for State, or adjust the array size.

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

4 Comments

thank you! I did not know I needed a default constructor for the the non-default initialized elements.
@Mihai - Each c'tor is a different way to initialize objects of your class. The first two don't need it. It's the rest. You can also provide it in another way. TVoidVoid function = nullptr will make your existing c'tor usable as a default c'tor too.
I'm a bit amazed that with extra {} (StoryTeller answer) and with less {} works too (my answer), but with the original quantity it did not.
@Mirko - Initialization in C++ is crazy, sadly.
1

You need a default constructor (for the last 8)

#include <array>

using TVoidVoid = void(*)(void);

class State{
public:
  // This static is equivalent to a TVoidVoid
  // used by the default constructor
  static void DefFunct() {}

  constexpr State(TVoidVoid function) : function_{function}{}

  // We create a default constructor for the 
  // empty elemnts of the array with our function
  constexpr State() : function_(DefFunct) {}

private:
  TVoidVoid function_;
};

void OnEvent1(){}
void OnEvent2(){}
constexpr std::array<State, 10> states = {OnEvent1, OnEvent2};

int main(){}

3 Comments

Thanks Mirko, I reformulated the question, but the code remains the same: I need an array of objects containing function pointers. I would like to construct these objects of type State in-place in the array.
@MihaiGalos Edited the answer.
So the remaining items need to be default-constructed, which was producing the error. Of course. All elements are statically constructed. Awesome. Please remove the first answer and leave the one after the edit, perhaps add a few comments why this is needed. Then we can close this question! Many thanks!

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.