views:

154

answers:

2

Hi, I am trying to initialize a 2D array of structs in C++, but am getting an error. Can someone please tell me what am I doing wrong? I have rechecked the braces and they seem to be fine.

My code:


struct CornerRotationInfo {
  bool does_breed;
  int breed_slope;
  bool self_inversion;
  int self_slope;
  inline CornerRotationInfo(bool db, int bs, bool si, int ss) : does_breed(db), breed_slope(bs), self_inversion(si), self_slope(ss) {};
};

#define NO false
#define YES true
#define R 1
#define F -1
#define H 0
static const CornerRotationInfo corner_rot_info[3][8] = {
  // { 0, 45, 90, 135
  //  180, 225, 270, 315 }
  {
    { NO, F, NO, F }, {YES, F, NO, H }, {YES, H, NO, R}, {NO, R, YES, R },
    { NO, F, NO, F }, {YES, F, NO, H }, {YES, H, NO, R}, {NO, R, YES, R }
  }, // Falling
  {
    { NO, H, NO, H }, {YES, F, NO, R }, {NO, H, YES, H }, {YES, R, NO, F },
    { NO, H, NO, H }, {YES, F, NO, R }, {NO, H, YES, H }, {YES, R, NO, F }
  }, // Horizontal
  {
    { NO, R, NO, R }, {NO, F, YES, F }, {YES, H, NO, F}, {YES, R, NO, H },
    { NO, R, NO, R }, {NO, F, YES, F }, {YES, H, NO, F}, {YES, R, NO, H }
  }  // Rising
};

#undef NO
#undef YES
#undef R
#undef F
#undef H

The error I am getting is:

Transformation.C:72: error: brace-enclosed initializer used to initialize `const
 CornerRotationInfo'
+1  A: 

If I understand your intention the problem is that you have given CornerRotationInfo a constructor. This means that it is no longer an aggregate structure and you can't use normal aggregate initialization.

If you remove the constructor your brace-enclosed initializer should work.

(If, on the other hand, you are trying to use C++0x's initializer_list you should make this clear in your question.)

Charles Bailey
+4  A: 

When you are trying to use aggregate initializer to initialize an array of objects with used-declared constructor, the syntax you can use depends significantly on how many parameters the individual element's constructor has.

If the constructor has (read: accepts) only one parameter, you can use "normal" aggregate initializer syntax, as in

std::string a[2] = { "abc", "def" };

However, if the constructor you want (or have) to use requires more than one parameter, you cannot pass the constructor arguments as a {}-enclosed list. You have no other choice but to explicitly create temporary objects of the target type in the aggregate initializer, as in

std::vector v[2] = { std::vector(10, 3), std::vector(8, 2) };

This is exactly what you have to do in your case

static const CornerRotationInfo corner_rot_info[3][8] = {
  {
    CornerRotationInfo(NO, F, NO, F), 
    CornerRotationInfo(YES, F, NO, H),
    ...
  },
  ...
};

and so on.

Note that in C++ initialization performed by an {}-enclosed initializer list is conceptually a copy-initialization, which means that you are not really changing much by creating those temporaries explicitly. I.e. conceptually the temporaries are always created during aggregate initialization. The compiler will normally optimize them away anyway.

AndreyT
Right on the money.
Allbite
Thanks AndreyT and all others.
JP19