Reputation: 41
I have the following structure:
struct myStruct {
long int mem0;
int mem1;
int mem2;
// -- Place 1 --
short int sh;
-- Place 2 --
char array[5];
// -- Place 3 --
};
I try to initialize it as follows:
struct myStruct ms1 = {
mem0 : 124,
mem1 : 120,
mem2 : 99,
mem3 : 12,
}; // Line 36
If I place any of the following lines in place 2 or place 3
char mem3;
int mem3;
I get the following error:
Azulejo-Main-Engine-1v2-4% g++ test2.cpp -o test2
test2.cpp: In function ‘int main()’:
test2.cpp:36:5: sorry, unimplemented: non-trivial designated initializers not supported
};
^
Azulejo-Main-Engine-1v2-4%
However, If I place it in place 1, my program compiles (and executes as expected). Can you please explain me why this is the case?.
I'm trying to port C code into C++. How can prevent this kind of errors?. I don't have any control on the structure declarations used by the code.
Azulejo-Main-Engine-1v2-4% g++ --version
g++ (GCC) 5.2.0
Upvotes: 3
Views: 6722
Reputation:
"sorry, unimplemented: <...>" always means that the compiler simply hasn't been updated to allow this yet. That's regardless of whether it will be allowed in the future, whether it is allowed by the standard, or whether it even makes sense.
As mentioned in the comments, this is not valid C++, this is a compiler extension. You can avoid problems of this kind by limiting yourself to valid C++. GCC will diagnose this and many other extensions if you pass it the -pedantic
flag. It will treat such extensions as a hard error if you pass it the -pedantic-errors
flag. If you then see that you are writing non-portable C++, update your code to make it portable, either by:
struct myStruct ms1 = {
124,
120,
99,
12
};
which requires you to place mem3
after mem2
, or by
struct myStruct ms1 {};
ms1.mem0 = 124;
ms1.mem1 = 120;
ms1.mem2 = 99;
ms1.mem3 = 12;
which does not require any specific placement of mem3
, or by adding a constructor to your myStruct
taking mem0
...mem3
as parameters.
Some extra details about the complications of this extension:
The initialisation of structures in C++ normally happens in whatever order the fields are declared. This makes handling exceptions fairly easy: the fields can be destroyed in the reverse order. If not all fields had been constructed yet, then start the destruction at the last field that had been constructed.
If you allow fields to be initialised in arbitrary order, then the destruction gets complicated. Given struct myStruct ms1 { mem1: f(), mem0: g() };
, if g
throws an exception, then either mem1
was already initialised and needs to be destructed, without mem0
also getting destructed, or the compiler rearranges the initialisers, meaning g()
gets called before f()
. The former is hard to get right in the compiler, the latter is very unintuitive.
A special exception could be made for trivially destructable fields, where no user code needs to be run when the fields are destroyed, but it hasn't been implemented yet.
If you place mem3
right after mem2
, then the problem is avoided: the order of initialisation matches the field order exactly.
Upvotes: 3