struct must be initialized by constructor?

I tried creating a second struct with a member from a first struct,
seems it need a constructor?
r2_sound works, but r2_word doesn’t.

I want to return a r2_word struct from r2_wordGen function. How to initialize r2_word?

r2d2.h

struct r2sound {
  int f0;
  int f1;
  float freqInc;
  int d0;
  int d1;
  float durInc;
  int soundlength;
};

struct r2word {
  r2sound soundA;
  int soundRepet;
  int repdelay;
  int order[6] = {0};
  //r2word(r2sound soundA, int repdelay, int order[6]) : soundA(soundA), repdelay(repdelay), order(order) {};
};

r2sound r2_soundGen(int flow, int fmaxi, int srIN0, int srIn1, int dmin, int dmax, int drIN0, int drIn1);
r2word r2_wordGen(r2sound sound0, int replow, int rephi, int rdellow, int rdelhi);

r2d2.ino

r2sound r2_soundGen(int flow, int fmaxi, int srIN0, int srIn1, int dmin, int dmax, int drIN0, int drIn1) {
  // word gen
  int f0 = TrueRandom.random(flow, fmaxi);
  int f1 = TrueRandom.random(flow, fmaxi);
  float freqInc = 1.0 + (abs(f0 -f1) / srIN0) + ((float)TrueRandom.random(srIn1, 100) / 100);
  int d0 = TrueRandom.random(dmin, dmax);
  int d1 = TrueRandom.random(dmin, dmax);
  float durInc = 1.0 + (abs(d0 -d1) / drIN0) + ((float)TrueRandom.random(drIn1, 100) / 100);
  int soundlength = r2_sound(f0, f1, freqInc, d0, d1, durInc, 1); 
  r2sound R2S = {f0, f1, freqInc, d0, d1, durInc, soundlength}; // THIS WORKS !!!
  return R2S;
}

r2word r2_wordGen(r2sound sound0, int replow, int rephi, int rdellow, int rdelhi) {
  int soundRepet = TrueRandom.random(replow, rephi);
  int repdelay = TrueRandom.random(rdellow, rdelhi);
  int order[6] = {0, 0, 0, 0, 0, 0};
  for(int i=0; i<6; i++){
    if (i < soundRepet) order[i] = random(1, 5);
    else order[i] = 0;
  }
  r2word R2W = {sound0, soundRepet, repdelay, order}; // HERE IS THE ERROR !!!
  return R2W;
}

Error:

r2d2.ino: In function 'r2word r2_wordGen(r2sound, int, int, int, int)':
r2d2.ino:53:52: error: in C++98 'R2W' must be initialized by constructor, not by '{...}'
r2d2.ino:53:52: error: could not convert '{sound0, soundRepet, repdelay, order}' from '<brace-enclosed initializer list>' to 'r2word'
Error compiling.
struct r2word {
  r2sound soundA;
  int soundRepet;
  int repdelay;
  int order[6] = {0};
  //r2word(r2sound soundA, int repdelay, int order[6]) : soundA(soundA), repdelay(repdelay), order(order) {};
};

You can't initialize non-const members like that. As the message says, do that in a constructor. For example, this fails:

struct foo 
  {
  int bar [10] = {0};  
  };

void setup () { }
void loop () { }
sketch_nov26b:3: error: a brace-enclosed initializer is not allowed here before ‘{’ token
sketch_nov26b:3: error: ISO C++ forbids initialization of member ‘bar’
sketch_nov26b:3: error: making ‘bar’ static
sketch_nov26b:3: error: invalid in-class initialization of static data member of non-integral type ‘int [10]’

This works:

struct foo 
  {
  int bar [10]; 
  public:
    foo () { memset (&bar, 0, sizeof bar); } // constructor
  };

void setup () { }
void loop () { }

@ nick.. +1

Doc

Thank for the patience ! I distilled out the problem ,and finally solved.
I didn’t know about that memset trick !

Here you can copy-paste this code finally working. I just had to pass a pointer to a r2word struct, I can initialize with a curly bracket style syntax.

I think constructor is unnecessary because this is not a class, I don’t need a function for initialization.

Print is because I checked that sound0 object is copied to a memory. Its not refer to a same object.

test02.ino

#include <test02.h>

r2sound r2_soundGen(int slength) {
  r2sound R2S = {slength};
  return R2S;
}

r2word r2_wordGen(r2sound sound0) {
  int order[6] = {0};
  r2word R2W = {sound0, 0, 0, *order};
  return R2W;
} 

void setup() {
	Serial.begin(9600);
    r2sound R2S = r2_soundGen(0);
  	r2word R2W = r2_wordGen(R2S);
  	Serial.println(R2S.soundlength);
  	R2W.soundA.soundlength = 1;
  	Serial.println(R2S.soundlength);
  	Serial.println(R2W.soundA.soundlength);
}

void loop() {}

test02.h

#include <stdio.h>
#include <string.h>

struct r2sound {
  int soundlength;
};

struct r2word {
  r2sound soundA;
  int soundRepet;
  int repdelay;
  int order[6];
};

r2sound r2_soundGen();
r2word r2_wordGen(r2sound sound0);

You can initialize using a brace enclosed initializer list due to the class being a POD. A class with a constructor, derived members or protected/private sections are not POD objects.

If you eventually need a constructor or other features which prevent the class from being a POD object, C++11 helps out here, it allows you to initialize arrays/PODs in the initializer list:

struct foo{
  int bar [10]; 
  
  foo() : bar{0} {}
};