C++ Structure Initialization [duplicate] - c++

This question already has answers here:
Designated initializers in C++20
(2 answers)
Closed 4 months ago.
Is it possible to initialize structs in C++ as indicated below:
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
address temp_address = { .city = "Hamilton", .prov = "Ontario" };
The links here and here mention that it is possible to use this style only in C. If so why is this not possible in C++? Is there any underlying technical reason why it is not implemented in C++, or is it bad practice to use this style. I like using this way of initializing because my struct is big and this style gives me clear readability of what value is assigned to which member.
Please share with me if there are other ways through which we can achieve the same readability.
I have referred the following links before posting this question:
C/C++ for AIX
C Structure Initialization with Variable
Static structure initialization with tags in C++
C++11 Proper Structure Initialization

If you want to make it clear what each initializer value is, just split it up on multiple lines, with a comment on each:
address temp_addres = {
0, // street_no
nullptr, // street_name
"Hamilton", // city
"Ontario", // prov
nullptr, // postal_code
};

After my question resulted in no satisfying result (because C++ doesn't implement tag-based init for structures), I took the trick I found here: Are members of a C++ struct initialized to 0 by default?
For you it would amount to do that:
address temp_address = {}; // will zero all fields in C++
temp_address.city = "Hamilton";
temp_address.prov = "Ontario";
This is certainly the closest to what you wanted originally (zero all the fields except those you want to initialize).

As others have mentioned this is designated initializer.
This feature is part of C++20

The field identifiers are indeed C initializer syntax. In C++ just give the values in the correct order without the field names. Unfortunately this means you need to give them all (actually you can omit trailing zero-valued fields and the result will be the same):
address temp_address = { 0, 0, "Hamilton", "Ontario", 0 };

This feature is called designated initializers. It is an addition to the C99 standard. However, this feature was left out of the C++11. According to The C++ Programming Language, 4th edition, Section 44.3.3.2 (C Features Not Adopted by C++):
A few additions to C99 (compared with C89) were deliberately not adopted in C++:
[1] Variable-length arrays (VLAs); use vector or some form of dynamic array
[2] Designated initializers; use constructors
The C99 grammar has the designated initializers [See ISO/IEC 9899:2011, N1570 Committee Draft - April 12, 2011]
6.7.9 Initialization
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designation_opt initializer
initializer-list , designationopt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
On the other hand, the C++11 does not have the designated initializers [See ISO/IEC 14882:2011, N3690 Committee Draft - May 15, 2013]
8.5 Initializers
initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
initializer-list:
initializer-clause ...opt
initializer-list , initializer-clause ...opt
braced-init-list:
{ initializer-list ,opt }
{ }
In order to achieve the same effect, use constructors or initializer lists:

I know this question is quite old, but I found another way of initializing, using constexpr and currying:
struct mp_struct_t {
public:
constexpr mp_struct_t(int member1) : mp_struct_t(member1, 0, 0) {}
constexpr mp_struct_t(int member1, int member2, int member3) : member1(member1), member2(member2), member3(member3) {}
constexpr mp_struct_t another_member(int member) { return {member1, member, member3}; }
constexpr mp_struct_t yet_another_one(int member) { return {member1, member2, member}; }
int member1, member2, member3;
};
static mp_struct_t a_struct = mp_struct_t{1}
.another_member(2)
.yet_another_one(3);
This method also works for global static variables and even constexpr ones.
The only disadvantage is the bad maintainability: Everytime another member has to be made initializable using this method, all member initialization methods have to be changed.

You can just initialize via a constructor:
struct address {
address() : city("Hamilton"), prov("Ontario") {}
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};

I might be missing something here, by why not:
#include <cstdio>
struct Group {
int x;
int y;
const char* s;
};
int main()
{
Group group {
.x = 1,
.y = 2,
.s = "Hello it works"
};
printf("%d, %d, %s", group.x, group.y, group.s);
}

You can even pack Gui13's solution into single initialization statement:
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
address ta = (ta = address(), ta.city = "Hamilton", ta.prov = "Ontario", ta);
Disclaimer: I don't recommend this style

It's not implemented in C++. (also, char* strings? I hope not).
Usually if you have so many parameters it is a fairly serious code smell. But instead, why not simply value-initialize the struct and then assign each member?

Inspired by this really neat answer: (https://stackoverflow.com/a/49572324/4808079)
You can do lamba closures:
// Nobody wants to remember the order of these things
struct SomeBigStruct {
int min = 1;
int mean = 3 ;
int mode = 5;
int max = 10;
string name;
string nickname;
... // the list goes on
}
.
class SomeClass {
static const inline SomeBigStruct voiceAmps = []{
ModulationTarget $ {};
$.min = 0;
$.nickname = "Bobby";
$.bloodtype = "O-";
return $;
}();
}
Or, if you want to be very fancy
#define DesignatedInit(T, ...)\
[]{ T ${}; __VA_ARGS__; return $; }()
class SomeClass {
static const inline SomeBigStruct voiceAmps = DesignatedInit(
ModulationTarget,
$.min = 0,
$.nickname = "Bobby",
$.bloodtype = "O-",
);
}
There are some drawbacks involved with this, mostly having to do with uninitialized members. From what the linked answers comments say, it compiles efficiently, though I have not tested it.
Overall, I just think it's a neat approach.

I found this way of doing it for global variables, that does not require to modify the original structure definition :
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
then declare the variable of a new type inherited from the original struct type and use the constructor for fields initialisation :
struct temp_address : address { temp_address() {
city = "Hamilton";
prov = "Ontario";
} } temp_address;
Not quite as elegant as the C style though ...
For a local variable it requires an additional memset(this, 0, sizeof(*this)) at the beginning of the constructor, so it's clearly not worse it and #gui13 's answer is more appropriate.
(Note that 'temp_address' is a variable of type 'temp_address', however this new type inherit from 'address' and can be used in every place where 'address' is expected, so it's OK.)

In C++ the C-style initializers were replaced by constructors which by compile time can ensure that only valid initializations are performed (i.e. after initialization the object members are consistent).
It is a good practice, but sometimes a pre-initialization is handy, like in your example. OOP solves this by abstract classes or creational design patterns.
In my opinion, using this secure way kills the simplicity and sometimes the security trade-off might be too expensive, since simple code does not need sophisticated design to stay maintainable.
As an alternative solution, I suggest to define macros using lambdas to simplify the initialization to look almost like C-style:
struct address {
int street_no;
const char *street_name;
const char *city;
const char *prov;
const char *postal_code;
};
#define ADDRESS_OPEN [] { address _={};
#define ADDRESS_CLOSE ; return _; }()
#define ADDRESS(x) ADDRESS_OPEN x ADDRESS_CLOSE
The ADDRESS macro expands to
[] { address _={}; /* definition... */ ; return _; }()
which creates and calls the lambda. Macro parameters are also comma separated, so you need to put the initializer into brackets and call like
address temp_address = ADDRESS(( _.city = "Hamilton", _.prov = "Ontario" ));
You could also write generalized macro initializer
#define INIT_OPEN(type) [] { type _={};
#define INIT_CLOSE ; return _; }()
#define INIT(type,x) INIT_OPEN(type) x INIT_CLOSE
but then the call is slightly less beautiful
address temp_address = INIT(address,( _.city = "Hamilton", _.prov = "Ontario" ));
however you can define the ADDRESS macro using general INIT macro easily
#define ADDRESS(x) INIT(address,x)

In GNUC++ (seems to be obsolete since 2.5, a long time ago :) See the answers here: C struct initialization using labels. It works, but how?), it is possible to initialize a struct like this:
struct inventory_item {
int bananas;
int apples;
int pineapples;
};
inventory_item first_item = {
bananas: 2,
apples: 49,
pineapples: 4
};

You have
The standard initialization list
address temp_address {
/* street_no */,
/* street_name */,
...
/* postal_code */
};
address temp_address2 = {
/* street_no */,
/* street_name */,
...
/* postal_code */
}
The dot notation
address temp_address;
temp_address.street_no = ...;
temp_address.street_name = ...;
...
temp_address.postal_code = ...;
The designated aggregate initialization, where the initialization list contains that labels of each member of the structure (see documentation) available from C++20 onward.
Treating a struct like a C++ class - in C++ structures are actually special types of classes, where all members are public (unlike a standard C++ class where all members are private if not specified otherwise explicitly) as well as that when using inheritance they default to public:
struct Address {
int street_no;
...
char* postal_code;
Address (int _street_no, ... , char* _postal_code)
: street_no(_street_no),
...
postal_code(_postal_code)
{}
}
...
Address temp_address ( /* street_no */, ..., /* postal_code */);
When it comes to the way you initialize your structure you should consider the following aspects:
Portability - different compilers, different degree of C++ standard completeness and different C++ standards altogether do limit your options. If you have to work with let's say a C++11 compiler but want to use the C++20 designated aggregate initialization you are out of luck
Readability - what is more readable: temp_address.city = "Toronto" or temp_address { ..., "Toronto", ... }? Readability of your code is very important. Especially when you have large structures (worse - nested ones), having unlabeled values all over the place is just asking for trouble
Scalability - anything that depends on a specific order is not a good idea. The same goes for lack of labels. You want to move a member up or down the address space of the structure? Good luck with an unlabeled initialization list (hunting down swapped values in structure initialization is a nightmare)... You want to add a new member? Again good luck with anything that depends on a specific order.
While the dot notation means you type more the benefits you get from using it outweigh this issue and as such I can recommend it unless you have a small structure that is future-proof in terms of lack of changes in its structure, in which case you can afford to go with an initialization list. Remember: whenever working with other people writing code that is easy to follow is essential.

I faced a similar problem today, where I have a struct that I want to fill with test data which will be passed as arguments to a function I'm testing. I wanted to have a vector of these structs and was looking for a one-liner method to initialize each struct.
I ended up going with a constructor function in the struct, which I believe was also suggested in a few answers to your question.
It's probably bad practice to have the arguments to the constructor have the same names as the public member variables, requiring use of the this pointer. Someone can suggest an edit if there is a better way.
typedef struct testdatum_s {
public:
std::string argument1;
std::string argument2;
std::string argument3;
std::string argument4;
int count;
testdatum_s (
std::string argument1,
std::string argument2,
std::string argument3,
std::string argument4,
int count)
{
this->rotation = argument1;
this->tstamp = argument2;
this->auth = argument3;
this->answer = argument4;
this->count = count;
}
} testdatum;
Which I used in in my test function to call the function being tested with various arguments like this:
std::vector<testdatum> testdata;
testdata.push_back(testdatum("val11", "val12", "val13", "val14", 5));
testdata.push_back(testdatum("val21", "val22", "val23", "val24", 1));
testdata.push_back(testdatum("val31", "val32", "val33", "val34", 7));
for (std::vector<testdatum>::iterator i = testdata.begin(); i != testdata.end(); ++i) {
function_in_test(i->argument1, i->argument2, i->argument3, i->argument4m i->count);
}

It is possible, but only if the struct you're initializing is a POD (plain old data) struct. It cannot contain any methods, constructors, or even default values.

Related

How do I create a function to initialize a struct object in C++? [duplicate]

This question already has answers here:
Designated initializers in C++20
(2 answers)
Closed 4 months ago.
Is it possible to initialize structs in C++ as indicated below:
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
address temp_address = { .city = "Hamilton", .prov = "Ontario" };
The links here and here mention that it is possible to use this style only in C. If so why is this not possible in C++? Is there any underlying technical reason why it is not implemented in C++, or is it bad practice to use this style. I like using this way of initializing because my struct is big and this style gives me clear readability of what value is assigned to which member.
Please share with me if there are other ways through which we can achieve the same readability.
I have referred the following links before posting this question:
C/C++ for AIX
C Structure Initialization with Variable
Static structure initialization with tags in C++
C++11 Proper Structure Initialization
If you want to make it clear what each initializer value is, just split it up on multiple lines, with a comment on each:
address temp_addres = {
0, // street_no
nullptr, // street_name
"Hamilton", // city
"Ontario", // prov
nullptr, // postal_code
};
After my question resulted in no satisfying result (because C++ doesn't implement tag-based init for structures), I took the trick I found here: Are members of a C++ struct initialized to 0 by default?
For you it would amount to do that:
address temp_address = {}; // will zero all fields in C++
temp_address.city = "Hamilton";
temp_address.prov = "Ontario";
This is certainly the closest to what you wanted originally (zero all the fields except those you want to initialize).
As others have mentioned this is designated initializer.
This feature is part of C++20
The field identifiers are indeed C initializer syntax. In C++ just give the values in the correct order without the field names. Unfortunately this means you need to give them all (actually you can omit trailing zero-valued fields and the result will be the same):
address temp_address = { 0, 0, "Hamilton", "Ontario", 0 };
This feature is called designated initializers. It is an addition to the C99 standard. However, this feature was left out of the C++11. According to The C++ Programming Language, 4th edition, Section 44.3.3.2 (C Features Not Adopted by C++):
A few additions to C99 (compared with C89) were deliberately not adopted in C++:
[1] Variable-length arrays (VLAs); use vector or some form of dynamic array
[2] Designated initializers; use constructors
The C99 grammar has the designated initializers [See ISO/IEC 9899:2011, N1570 Committee Draft - April 12, 2011]
6.7.9 Initialization
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designation_opt initializer
initializer-list , designationopt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
On the other hand, the C++11 does not have the designated initializers [See ISO/IEC 14882:2011, N3690 Committee Draft - May 15, 2013]
8.5 Initializers
initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
initializer-list:
initializer-clause ...opt
initializer-list , initializer-clause ...opt
braced-init-list:
{ initializer-list ,opt }
{ }
In order to achieve the same effect, use constructors or initializer lists:
I know this question is quite old, but I found another way of initializing, using constexpr and currying:
struct mp_struct_t {
public:
constexpr mp_struct_t(int member1) : mp_struct_t(member1, 0, 0) {}
constexpr mp_struct_t(int member1, int member2, int member3) : member1(member1), member2(member2), member3(member3) {}
constexpr mp_struct_t another_member(int member) { return {member1, member, member3}; }
constexpr mp_struct_t yet_another_one(int member) { return {member1, member2, member}; }
int member1, member2, member3;
};
static mp_struct_t a_struct = mp_struct_t{1}
.another_member(2)
.yet_another_one(3);
This method also works for global static variables and even constexpr ones.
The only disadvantage is the bad maintainability: Everytime another member has to be made initializable using this method, all member initialization methods have to be changed.
You can just initialize via a constructor:
struct address {
address() : city("Hamilton"), prov("Ontario") {}
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
I might be missing something here, by why not:
#include <cstdio>
struct Group {
int x;
int y;
const char* s;
};
int main()
{
Group group {
.x = 1,
.y = 2,
.s = "Hello it works"
};
printf("%d, %d, %s", group.x, group.y, group.s);
}
You can even pack Gui13's solution into single initialization statement:
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
address ta = (ta = address(), ta.city = "Hamilton", ta.prov = "Ontario", ta);
Disclaimer: I don't recommend this style
It's not implemented in C++. (also, char* strings? I hope not).
Usually if you have so many parameters it is a fairly serious code smell. But instead, why not simply value-initialize the struct and then assign each member?
Inspired by this really neat answer: (https://stackoverflow.com/a/49572324/4808079)
You can do lamba closures:
// Nobody wants to remember the order of these things
struct SomeBigStruct {
int min = 1;
int mean = 3 ;
int mode = 5;
int max = 10;
string name;
string nickname;
... // the list goes on
}
.
class SomeClass {
static const inline SomeBigStruct voiceAmps = []{
ModulationTarget $ {};
$.min = 0;
$.nickname = "Bobby";
$.bloodtype = "O-";
return $;
}();
}
Or, if you want to be very fancy
#define DesignatedInit(T, ...)\
[]{ T ${}; __VA_ARGS__; return $; }()
class SomeClass {
static const inline SomeBigStruct voiceAmps = DesignatedInit(
ModulationTarget,
$.min = 0,
$.nickname = "Bobby",
$.bloodtype = "O-",
);
}
There are some drawbacks involved with this, mostly having to do with uninitialized members. From what the linked answers comments say, it compiles efficiently, though I have not tested it.
Overall, I just think it's a neat approach.
I found this way of doing it for global variables, that does not require to modify the original structure definition :
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
then declare the variable of a new type inherited from the original struct type and use the constructor for fields initialisation :
struct temp_address : address { temp_address() {
city = "Hamilton";
prov = "Ontario";
} } temp_address;
Not quite as elegant as the C style though ...
For a local variable it requires an additional memset(this, 0, sizeof(*this)) at the beginning of the constructor, so it's clearly not worse it and #gui13 's answer is more appropriate.
(Note that 'temp_address' is a variable of type 'temp_address', however this new type inherit from 'address' and can be used in every place where 'address' is expected, so it's OK.)
In C++ the C-style initializers were replaced by constructors which by compile time can ensure that only valid initializations are performed (i.e. after initialization the object members are consistent).
It is a good practice, but sometimes a pre-initialization is handy, like in your example. OOP solves this by abstract classes or creational design patterns.
In my opinion, using this secure way kills the simplicity and sometimes the security trade-off might be too expensive, since simple code does not need sophisticated design to stay maintainable.
As an alternative solution, I suggest to define macros using lambdas to simplify the initialization to look almost like C-style:
struct address {
int street_no;
const char *street_name;
const char *city;
const char *prov;
const char *postal_code;
};
#define ADDRESS_OPEN [] { address _={};
#define ADDRESS_CLOSE ; return _; }()
#define ADDRESS(x) ADDRESS_OPEN x ADDRESS_CLOSE
The ADDRESS macro expands to
[] { address _={}; /* definition... */ ; return _; }()
which creates and calls the lambda. Macro parameters are also comma separated, so you need to put the initializer into brackets and call like
address temp_address = ADDRESS(( _.city = "Hamilton", _.prov = "Ontario" ));
You could also write generalized macro initializer
#define INIT_OPEN(type) [] { type _={};
#define INIT_CLOSE ; return _; }()
#define INIT(type,x) INIT_OPEN(type) x INIT_CLOSE
but then the call is slightly less beautiful
address temp_address = INIT(address,( _.city = "Hamilton", _.prov = "Ontario" ));
however you can define the ADDRESS macro using general INIT macro easily
#define ADDRESS(x) INIT(address,x)
In GNUC++ (seems to be obsolete since 2.5, a long time ago :) See the answers here: C struct initialization using labels. It works, but how?), it is possible to initialize a struct like this:
struct inventory_item {
int bananas;
int apples;
int pineapples;
};
inventory_item first_item = {
bananas: 2,
apples: 49,
pineapples: 4
};
You have
The standard initialization list
address temp_address {
/* street_no */,
/* street_name */,
...
/* postal_code */
};
address temp_address2 = {
/* street_no */,
/* street_name */,
...
/* postal_code */
}
The dot notation
address temp_address;
temp_address.street_no = ...;
temp_address.street_name = ...;
...
temp_address.postal_code = ...;
The designated aggregate initialization, where the initialization list contains that labels of each member of the structure (see documentation) available from C++20 onward.
Treating a struct like a C++ class - in C++ structures are actually special types of classes, where all members are public (unlike a standard C++ class where all members are private if not specified otherwise explicitly) as well as that when using inheritance they default to public:
struct Address {
int street_no;
...
char* postal_code;
Address (int _street_no, ... , char* _postal_code)
: street_no(_street_no),
...
postal_code(_postal_code)
{}
}
...
Address temp_address ( /* street_no */, ..., /* postal_code */);
When it comes to the way you initialize your structure you should consider the following aspects:
Portability - different compilers, different degree of C++ standard completeness and different C++ standards altogether do limit your options. If you have to work with let's say a C++11 compiler but want to use the C++20 designated aggregate initialization you are out of luck
Readability - what is more readable: temp_address.city = "Toronto" or temp_address { ..., "Toronto", ... }? Readability of your code is very important. Especially when you have large structures (worse - nested ones), having unlabeled values all over the place is just asking for trouble
Scalability - anything that depends on a specific order is not a good idea. The same goes for lack of labels. You want to move a member up or down the address space of the structure? Good luck with an unlabeled initialization list (hunting down swapped values in structure initialization is a nightmare)... You want to add a new member? Again good luck with anything that depends on a specific order.
While the dot notation means you type more the benefits you get from using it outweigh this issue and as such I can recommend it unless you have a small structure that is future-proof in terms of lack of changes in its structure, in which case you can afford to go with an initialization list. Remember: whenever working with other people writing code that is easy to follow is essential.
I faced a similar problem today, where I have a struct that I want to fill with test data which will be passed as arguments to a function I'm testing. I wanted to have a vector of these structs and was looking for a one-liner method to initialize each struct.
I ended up going with a constructor function in the struct, which I believe was also suggested in a few answers to your question.
It's probably bad practice to have the arguments to the constructor have the same names as the public member variables, requiring use of the this pointer. Someone can suggest an edit if there is a better way.
typedef struct testdatum_s {
public:
std::string argument1;
std::string argument2;
std::string argument3;
std::string argument4;
int count;
testdatum_s (
std::string argument1,
std::string argument2,
std::string argument3,
std::string argument4,
int count)
{
this->rotation = argument1;
this->tstamp = argument2;
this->auth = argument3;
this->answer = argument4;
this->count = count;
}
} testdatum;
Which I used in in my test function to call the function being tested with various arguments like this:
std::vector<testdatum> testdata;
testdata.push_back(testdatum("val11", "val12", "val13", "val14", 5));
testdata.push_back(testdatum("val21", "val22", "val23", "val24", 1));
testdata.push_back(testdatum("val31", "val32", "val33", "val34", 7));
for (std::vector<testdatum>::iterator i = testdata.begin(); i != testdata.end(); ++i) {
function_in_test(i->argument1, i->argument2, i->argument3, i->argument4m i->count);
}
It is possible, but only if the struct you're initializing is a POD (plain old data) struct. It cannot contain any methods, constructors, or even default values.

Const struct initialization with custom elements in C++

I am porting some C code to C++ and I am trying to initialize a struct with some values.
I want the struct to be stored in flash (const) and not in RAM, and its values are typedef'd elements.
Originally, I had it like this:
typedef struct
{
typeA_t elementA;
typeB_t elementB;
uint8_t elementC;
} structTypeA_t;
And to instantiate them in flash, I simply did the following:
const structTypeA_t sA = {
.elementA = ONE,
.elementB = TWO,
.elementC = 3
};
I know that this type of initializing is not allowed in C++. How can I achieve it in C++?
Designated initializers are not in C++ (yet, but look for C++20). So you do it almost the same way, but without names - position of the argument defines the field it initializes:
const structTypeA_t sA = {ONE,
TWO,
3
};
If you always need to initialize with the same values, then you can just define the struct like this:
struct structTypeA_t
{
typeA_t elementA = ONE;
typeB_t elementB = TWO;
uint8_t elementC = 3;
};
You can now instantiate it without an initializer:
const structTypeA_t sA;

Make a C++ initializer automatically detect union member?

OK, the standard still says that brace-initializing a union initializes only the first member. I suppose this puts this question more in the "Wouldn't it be nice if...?" category.
Does it have to be this way? After all, we now have automatic type detection for other types.
auto x = 3; // int
auto s = "foo"; // char *
auto w = L"Foo"; // wchar_t *
So why not with a union? Given:
struct init
{
int t;
union {
long long x;
char *s;
wchar_t *w;
};
};
Currently you can only brace-initialize init::x (with an int), not s or w.
Automatic type detection might be extended so that the union member initialized is selected based on the type of the initializer:
auto init initial_data [] = {
{ 0, 3 }, // initializes x, brace elision
{ 1, "foo" }, // initializes s
{ 2, L"Foo" } // initializes w
};
(of course, this should not compile in the current standard.)
This would make it possible to put all of the initial_data in a single initializer list. (I suspect the auto keyword would have to go somewhere else).
Is there something making this a Bad Idea (beyond "nobody's thought of it yet" or "it's too hard to implement")? Currently you have to do something horrendous like:
#define RI(X) reinterpret_cast<long long>(X)
const init initial_data[] = {
{ 0, 3 }, // initializes x, brace elision
{ 1, RI("foo") }, // initializes s
{ 2, RI(L"Foo") } // initializes w
};
I wouldn't want to go through these contortions, except that a std::exception must be initialized with a std::string (i.e. based on char), so I can't just have an initializer list with all wchar_t*. And I'd really like all of those initializers in the same place.
Update
In my introduction I mentioned:
(though A union can have member functions (including constructors and destructors)
I just realized this enables you to write the required constructors yourself!
struct init {
init(long long v) : t(type::longlong), x(v) {}
init(char const* v) : t(type::pcsz), s(v) {}
init(wchar_t const* v) : t(type::pwcsz), w(v) {}
enum class type { longlong, pcsz, pwcsz } t;
union { long long x; char const* s; wchar_t const* w; };
};
Now this compiles:
init initial_data [] = {
3 , // initializes x, brace elision
"foo" , // initializes s
L"Foo" // initializes w
};
See it Live On Coliru
Q. Is there something making this a Bad Idea (beyond "nobody's thought of it yet" or "it's too hard to implement")
In general union are very often a bad idea. It's hard to use them safely. In this respect they're a bit "second class" citizens in C++ (though A union can have member functions (including constructors and destructors), but not virtual functions, these days).
Letting the compiler select "the" slot to receive the initializer is likely to run into ambiguities very soon.
With brace initialization, they could add some restrictions (no narrowing/widening conversions) like there already are with initializer lists in C++11.
But this is all fantasy. The short of it is: this is not a language feature.
boost::variant has this behaviour.
Notes
the which() member is basically your type discriminator (t)
you can optimize for size: BOOST_VARIANT_MINIMIZE_SIZE
you should make the char/wchar_t pointers const* if you want to assign from a literal!
Live On Coliru
#define BOOST_VARIANT_MINIMIZE_SIZE
#include <boost/variant.hpp>
using init = boost::variant<long long, char const*, wchar_t const*>;
#include <iostream>
int main() {
init initial_data [] = {
3 , // initializes x, brace elision
"foo" , // initializes s
L"Foo" // initializes w
};
for(auto& v : initial_data)
std::cout << v.which() << "\t" << v << "\n";
}
Output:
0 3
1 foo
2 0x401f14

how to initialize a static struct in c++?

I have managed to initialize correct any variable of basic type(i.e. int, char, float etc) but when declaring a little complex variable all i can see is errors.
In the header file timer.h i declare
class AndroidTimerConcept {
...
private:
//struct that holds the necessary info for every event
struct Resources{
timer_delegate_t membFunct;
void *data;
int size;
millis_t time;
};
//declaring an array of 10 Resources structs
static struct Resources ResData;
static int best;
...
}
inside the timer.cpp file
#include <iostream>
#include "timer.h"
using namespace std;
int AndroidTimerModel::best=1000;
struct Resources AndroidTimerModel::ResData.size; //line 17!!
//constructor that initializes all the necessary variables
AndroidTimerModel::AndroidTimerModel()
{
signal(SIGALRM,signalHandler);
for(int i=0; i<MAX_EVENTS; i++)
{
//ResData.data=NULL;
ResData.size=-1;
//ResData.time=-1;
}
best=1000;
}
when compiling the .cpp file i get the error:
timer.cpp:7: error: expected initializer before ‘.’ token
Any suggestions would be really helpful.
btw i use g++
You can use a struct initializer in C++, but only in the pre-C99 style (i.e, you cannot use designated initializers). Designated intializers, which allow you to specify the members to be initialized by name, rather than relying on declaration order, were introduced in C99, but aren't part of any C++ standard at the moment (belying the common assumption that C++ is a superset of C).
If you are willing to write non-portable C++ code that specifically targets g++, you can always use the GCC-specific extension which has the same functionality as designated constructors. The syntax is like this:
struct value_t my_val = { member_a: 1, member_b: 1.2f };
This reference provides a pretty good overview of both types of initialization in the C context.
Here's an excerpt that shows both the earlier (without designators) and C99 styles:
When initializing a struct, the first initializer in the list
initializes the first declared member (unless a designator is
specified) (since C99), and all subsequent initializers without
designators (since C99) initialize the struct members declared after
the one initialized by the previous expression.
struct point {double x,y,z;} p = {1.2, 1.3}; // p.x=1.2, p.y=1.3, p.z=0.0
div_t answer = {.quot = 2, .rem = -1 }; // order of elements in div_t may vary
In some cases you may need to write some code to initialize a structure, and in this case you can use the result of a function, like:
struct Resources AndroidTimerModel::ResData = function_that_acts_like_a_constructor();
You don't separately define individual instance members within a static member.
This should be enough:
AndroidTimerModel::Resources AndroidTimerModel::ResData;
You need to declare and define a constructor for struct Resources.
eg
struct Resources{
timer_delegate_t membFunct;
void *data;
int size;
millis_t time;
Resources():membFunct(0), data(0), size(0), time(0) {}
....
};
You need to initialise the whole struct variable, something like this:
AndroidTimerConcept::Resources AndroidTimerModel::ResData = { NULL, NULL, 0, 0 };
Is it AndroidTimerModel or AndroidTimerConcept, you can't use different names and expect the compiler to think they're the same thing.
You need to scope the name Resources, it's not in global scope, it's in the scope of the AndroidTimerModel class:
AndroidTimerModel::Resources AndroidTimerModel::ResData;
I suggest you give Resources a constructor:
struct Resources{
Resources(timer_delegate_t aMembFunct, void* aData, int aSize, millis_t aTime )
: membFunc(aMembFunct)
, data(aData)
, size(aSize)
, time(aTime)
{}
timer_delegate_t membFunct;
void *data;
int size;
millis_t time;
};
And you can then define Res in your .cpp as:
AndroidTimerModel::Resources AndroidTimerModel::ResData(/* params here */);
Why is your struct part of a class? I would make it global outside of the class.
memset(&structname, 0, sizeof(structname)); will initialize your structure to 0.

What is the best way to initialize a bitfield struct in C++?

In C++, I have a class which contains an anonymous bitfield struct. I want to initialize it to zero without having to manually write out all fields.
I can imagine putting the initialization in three places:
Create a constructor in the bitfield
Zero out in the initializer list of the constructor for the containing class
Zero out in the body of the constructor for the containing class
This bitfield has many fields, and I'd rather not list them all.
For example see the following code:
class Big {
public:
Big();
// Bitfield struct
struct bflag_struct {
unsigned int field1 : 1;
unsigned int field2 : 2;
unsigned int field3 : 1;
// ...
unsigned int field20 : 1;
// bflag_struct(); <--- Here?
} bflag;
unsigned int integer_member;
Big *pointer_member;
}
Big::Big()
: bflag(), // <--- Can I zero bflag here?
integer_member(0),
pointer_member(NULL)
{
// Or here?
}
Is one of these preferable? Or is there something else I'm missing?
Edit: Based on the accepted answer below (by Ferruccio) I settled on this solution:
class Big {
// ...
struct bflag_struct {
unsigned int field 1 : 1;
// ...
bflag_struct() { memset(this, 0, sizeof *this); };
}
// ...
}
You could always do this in your constructor:
memset(&bflag, 0, sizeof bflag);
Union the bitfield struct with something easier to initialize to 0.
You could use a union, although that would add an extra level of indirection when accessing the fields:
class Big {
union {
struct {
unsigned int field1 : 1;
...
} fields;
unsigned int all_fields;
};
...
};
Big::Big()
: all_fields(0),
...
{
...
}
MSVC allows anonymous structs inside of unions (see, e.g. the definition of D3DMATRIX in <d3d9.h>), but this is a non-standard C++ extension which you should avoid using if you can.
BTW C++20 supports initializing the bitfields in the class definition e.g.
class ... {
int foo : 1 {};
}
gcc with -std=c++2a to enable
Your use of a function-like initializer (marked "Can I zero bflag here?") is 100% sufficient to initialize your POD struct with 0 values.
Unless you know your compiler is broken in this regard, doing any additional initialization of those members is initializing it twice for no benefit.
EDIT: Just for 'fun' I just checked this with VS2005, VS2008, GCC 3.4.4, GCC 4.2, and Borland C++ 5.5.1 ... only Borland C++ 5.5.1 gets it wrong.
And I say 'wrong' because it seems to me that 8.5 and 8.5.1 of the standard imply that the function-like initializer should zero-init the POD struct.
As an aside, unless you need the bitfield to interface to some legacy code, you shouldn't use them. They are are inherently unportable and inefficient.
you could Zero the memory using ZeroMemory or memset in the constructor that way it look's cleaner.