Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++20 Designated initializers + struct member initializer

98 views
Skip to first unread message

Thiago Adams

unread,
Oct 14, 2020, 2:02:07 PM10/14/20
to

This sample prints:

https://godbolt.org/z/3f13vW

#include <stdio.h>

struct Point {
const char* name = "";
int x = 1, y = 2;
};

struct Line {
struct Point pt1 = { .name = "pt1" };
};

int main()
{
struct Line line = {};
printf(".pt1 = {.name='%s' .x=%d .y=%d}\n", line.pt1.name, line.pt1.x , line.pt1.y);


struct Line line2 = { .pt1 = {.x = 3} };
printf(".pt1 = {.name='%s' .x=%d .y=%d}\n", line2.pt1.name, line2.pt1.x , line2.pt1.y);
}


.pt1 = {.name='pt1' .x=1 .y=2}
.pt1 = {.name='' .x=3 .y=2}


I was expecting this for the last print:

.pt1 = {.name='pt1' .x=3 .y=2}


basically the designated initializers does not care
about the defaults of line.

I was expecting the designed initializer something that
could override the defaults but not ignore then.

What do you think? What is the rationale for this?



Thiago Adams

unread,
Oct 14, 2020, 2:04:44 PM10/14/20
to

Pankaj Jangid

unread,
Nov 8, 2020, 4:47:46 AM11/8/20
to
Thiago Adams <thiago...@gmail.com> writes:

> #include <stdio.h>
>
> struct Point {
> const char* name = ""; int x = 1, y = 2; };
>
> struct Line {
> struct Point pt1 = { .name = "pt1" }; };
>
> int main() {
> struct Line line = {}; printf(".pt1 = {.name='%s' .x=%d .y=%d}\n",
> line.pt1.name, line.pt1.x , line.pt1.y);
>
>
> struct Line line2 = { .pt1 = {.x = 3} }; printf(".pt1 =
> {.name='%s' .x=%d .y=%d}\n", line2.pt1.name, line2.pt1.x ,
> line2.pt1.y);
> }
>
>
> .pt1 = {.name='pt1' .x=1 .y=2} .pt1 = {.name='' .x=3 .y=2}
>
>
> I was expecting this for the last print:
>
> .pt1 = {.name='pt1' .x=3 .y=2}

It is like this,

struct Point pt1 = {.x = 3}

printf(".pt1 = {.name='%s' .x=%d .y=%d}\n", pt1.name, pt1.x, pt1.y);

struct Line line2 = {.pt1 = pt1}

printf(".pt1 = {.name='%s' .x=%d .y=%d}\n", line2.pt1.name, line2.pt1.x,
line2.pt1.y);

Should the first and the second printf statement print different output?

Christian Hanné

unread,
Nov 8, 2020, 1:18:31 PM11/8/20
to
Designated initializers aren't needed. There are constructors.

Ian Collins

unread,
Nov 8, 2020, 2:12:32 PM11/8/20
to
On 09/11/2020 07:18, Christian Hanné wrote:
> Designated initializers aren't needed. There are constructors.

Not for C structs used in C++ code there aren't...

--
Ian.

Christian Hanné

unread,
Nov 8, 2020, 2:13:35 PM11/8/20
to
>> Designated initializers aren't needed. There are constructors.

> Not for C structs used in C++ code there aren't...

Then you derive a C++-class from the C-struct with a constructor.

Ian Collins

unread,
Nov 8, 2020, 2:40:55 PM11/8/20
to
For simple cases that's fine, but it can get messy fast when there are
multiple structs and different fields require initialisation in
different contexts (Linux USB for example). I have resorted to mixing C
and C++ TUs to work around the lack of designated initialisers in C++.

--
Ian.

Keith Thompson

unread,
Nov 8, 2020, 4:27:27 PM11/8/20
to
Christian Hanné <the....@gmail.com> writes:
> Designated initializers aren't needed. There are constructors.

Loops aren't needed. There are gotos.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Christian Hanné

unread,
Nov 9, 2020, 3:03:36 AM11/9/20
to
>> Designated initializers aren't needed. There are constructors.

> Loops aren't needed. There are gotos.

That's an analogy in the opposite direction. Gotos are technically
less usable than loops. But constructors are more flexible than
designated initializers.

Juha Nieminen

unread,
Nov 9, 2020, 3:14:29 AM11/9/20
to
Christian Hanné <the....@gmail.com> wrote:
> Designated initializers aren't needed. There are constructors.

Show me how you do this with constructors:

struct S
{
int a = 1, b = 2, c = 3, d = 4, e = 5;
};

const S obj1 = { .b = 10, .d = 20 };
const S obj2 = { .d = 15, .e = 16 };
const S obj3 = { .a = 100, .c = 200, .e = 300 };

Christian Hanné

unread,
Nov 9, 2020, 3:19:59 AM11/9/20
to
> Show me how you do this with constructors:
> struct S
> {
> int a = 1, b = 2, c = 3, d = 4, e = 5;
> };
> const S obj1 = { .b = 10, .d = 20 };
> const S obj2 = { .d = 15, .e = 16 };
> const S obj3 = { .a = 100, .c = 200, .e = 300 };

That's not possible and not needed.
But the default-values make a lot of confusion since
they can be scattered in the defininition of the struct.
So better use constructors.

Ian Collins

unread,
Nov 9, 2020, 3:29:55 AM11/9/20
to
On 09/11/2020 21:19, Christian Hanné wrote:
>> Show me how you do this with constructors:
>> struct S
>> {
>> int a = 1, b = 2, c = 3, d = 4, e = 5;
>> };
>> const S obj1 = { .b = 10, .d = 20 };
>> const S obj2 = { .d = 15, .e = 16 };
>> const S obj3 = { .a = 100, .c = 200, .e = 300 };
>
> That's not possible and not needed.

Why not needed?

> But the default-values make a lot of confusion since
> they can be scattered in the defininition of the struct.

No, they don't.

> So better use constructors.

No, it isn't. If you need different members initialised in different
contexts, designated initialisers are your friend.

--
Ian.

Keith Thompson

unread,
Nov 9, 2020, 3:40:16 AM11/9/20
to
A while ago, Christian Hanné posted a lot of deliberate nonsense in
comp.lang.c. Don't expect reasonable replies.

Christian Hanné

unread,
Nov 9, 2020, 3:50:27 AM11/9/20
to
>> So better use constructors.

> No, it isn't.  If you need different members initialised in different
> contexts, designated initialisers are your friend.

I said why this confuses the reader. With constructors you have
the declaration of the construtor in a tooltip in your IDE, with
designated initializers you have to check the structure definition
first.

Christian Hanné

unread,
Nov 9, 2020, 3:51:08 AM11/9/20
to
> A while ago, Christian Hanné posted a lot of deliberate
> nonsense in comp.lang.c. Don't expect reasonable replies.

I never posted nonsense.

Juha Nieminen

unread,
Nov 9, 2020, 6:46:40 AM11/9/20
to
Christian Hanné <the....@gmail.com> wrote:
> I said why this confuses the reader. With constructors you have
> the declaration of the construtor in a tooltip in your IDE, with
> designated initializers you have to check the structure definition
> first.

Firstly, if understanding the code requires an IDE, then the code is badly
designed.

Secondly, if an IDE is able to show the constructor signature in a tooltip,
then certainly it can show the members of a struct in a designated
initalizer list? If not, and you rely so much on IDE tooltips, then get
a better IDE.

Thirdly, designated initializers make initialization a lot clearer
because they function, essentially, as named parameters, which is
something that constructors (and functions in general) have always lacked
in C++.

This is particularly handy for configuration headers and such, which may
be written and fine-tuned by team members other than the original programmer
(some of which may not be programmers at all). I have used this quite
extensively, to create "configuration" files like:

const Settings kSettings
{
.numberOfStuff = 123,
.aValueForSomething = 5,
.aFactorUsedForThis = 0.25,

.elements =
{
{ .amount = 5, .factor = 2.2, .seconds = 10 },
{ .amount = 8, .factor = 1.0, .seconds = 15 },
{ .amount = 1, .factor = 0.5, .seconds = 5 }
}
};

Even a complete non-coder can go and fine-tune those values without the
need to understand C++ (especially when the variables are named clearly
according to the context; obviously I used fictitious names above).

(In fact, I have used that technique quite a lot in some Objective-C++
programs, where the order of initialization doesn't need to match the
order of declaration. This is particularly handy because it allows the
initialization to use an ordering that's easy to read and understand,
while the declaration may use an ordering that's eg. optimized for
space, as the order of declaration of member variables matter in this
regard. It's a huge same that C++20 decided to put the limitation that
the initializers must be in the same order as the declaration.)

Christian Hanné

unread,
Nov 9, 2020, 6:50:33 AM11/9/20
to
> Firstly, if understanding the code requires an IDE, then the code is badly
> designed.

Wrong, an IDE has many facilities which can't be replaced by proper
coding.

> Secondly, if an IDE is able to show the constructor signature in a tooltip,
> then certainly it can show the members of a struct in a designated
> initalizer list? ...

Neither CLion, nor Visual Studio, nor Eclipse CDE can do this.

> Thirdly, designated initializers make initialization a lot clearer
> because they function, essentially, as named parameters, which is
> something that constructors (and functions in general) have always
> lacked in C++.

Therefore you have an IDE.

Haven't read the rest of your nonsense.

Juha Nieminen

unread,
Nov 9, 2020, 9:32:37 AM11/9/20
to
Christian Hanné <the....@gmail.com> wrote:
> Haven't read the rest of your nonsense.

I'll take that as a concession of defeat. If you can't answer to the
arguments given to you, that's because you don't have an answer. You
don't have any valid counter-argument. Therefore you just concede.
The only thing you can do at that point is act in an arrogant and
dismissive manner. I suppose the insults will soon follow.

Christian Hanné

unread,
Nov 9, 2020, 9:44:20 AM11/9/20
to
Why do you argue so if you do it the same way by not responding to
what I said ?

Juha Nieminen

unread,
Nov 9, 2020, 10:42:11 AM11/9/20
to
You didn't bother responding to all the arguments I made, but
you expect me to respond to all your arguments? Especially when
you have that kind of attitude?

Right.

Scott Lurndal

unread,
Nov 9, 2020, 11:10:14 AM11/9/20
to
You are responding to Bonita (who, when slips and forgets to
delete the attribution headers, shows that Bonita uses a
German locale in its newsreader).

Note this Hanne fellow also removes attributions and makes stupid
arguments.

Christian Hanné

unread,
Nov 9, 2020, 12:31:36 PM11/9/20
to
> You are responding to Bonita (who, when slips and forgets to
> delete the attribution headers, shows that Bonita uses a
> German locale in its newsreader).

Sorry, but please stop with this imputations.

Keith Thompson

unread,
Nov 9, 2020, 1:47:37 PM11/9/20
to
I don't know whether Christian Hanné is a sockpuppet for Bonita
or not. And frankly it doesn't matter. I suggest we avoid wasting
time debating that particular point. (I personally will not waste
time responding to Christian Hanné at all.)

Jorgen Grahn

unread,
Nov 9, 2020, 3:24:49 PM11/9/20
to
On Sun, 2020-11-08, Christian Hanné wrote:
> Designated initializers aren't needed. There are constructors.

To my surprise, I agree. In fact, I thought everyone agreed on this,
and that that's why it wasn't squeezed into C++11.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Juha Nieminen

unread,
Nov 10, 2020, 2:03:36 AM11/10/20
to
Jorgen Grahn <grahn...@snipabacken.se> wrote:
> On Sun, 2020-11-08, Christian Hanné wrote:
>> Designated initializers aren't needed. There are constructors.
>
> To my surprise, I agree. In fact, I thought everyone agreed on this,
> and that that's why it wasn't squeezed into C++11.

For and while loops aren't needed either, nor switch constructs, nor
templates, or even classes. Or pretty much anything. Even C is way too
high level and has way too many useless features. A programming
language with just two instructions is Turing complete, and thus you
can implement anything with it. Nothing more is needed.

Christian Hanné

unread,
Nov 10, 2020, 2:32:12 AM11/10/20
to
> For and while loops aren't needed either, nor switch constructs, nor
> templates, or even classes. ...

That's polemic.
We're talking about dropping a less usable feature for a more usable.

David Brown

unread,
Nov 10, 2020, 4:47:06 AM11/10/20
to
On 09/11/2020 21:24, Jorgen Grahn wrote:
> On Sun, 2020-11-08, Christian Hanné wrote:
>> Designated initializers aren't needed. There are constructors.
>
> To my surprise, I agree. In fact, I thought everyone agreed on this,
> and that that's why it wasn't squeezed into C++11.
>

Certainly constructors can cover many of the use-cases of designated
initializers. And clearly constructors can do far more than designated
initializers can do. But in many simple cases, designated initializers
are simply easier and more convenient in the code. They are not
/needed/ - but neither is 90%+ of C++ /needed/. They are /wanted/. It
is a commonly requested feature, and has been supported as an extension
by some C++ compilers for quite a while.

David Brown

unread,
Nov 10, 2020, 4:49:16 AM11/10/20
to
No, we are not.

We are talking about /adding/ a useful feature to C++ - a feature that
exists already and is useful in C. No one is dropping anything.

Christian Hanné

unread,
Nov 10, 2020, 6:36:27 AM11/10/20
to
>> That's polemic.
>> We're talking about dropping a less usable feature for a more usable.

> No, we are not.
> We are talking about /adding/ a useful feature to C++ - a feature that
> exists already and is useful in C. No one is dropping anything.

That's not necessary because we have constructors.

David Brown

unread,
Nov 10, 2020, 7:47:06 AM11/10/20
to
Do you realise your posts are making no sense, and your arguments don't
hang together? If the answer is yes, you are trolling - and there's no
point in continuing. If the answer is no, you are not capable of
holding a sensible discussion and there's no point in continuing.


Christian Hanné

unread,
Nov 10, 2020, 7:51:49 AM11/10/20
to
> Do you realise your posts are making no sense, and your arguments don't
> hang together? If the answer is yes, you are trolling - and there's no
> point in continuing. If the answer is no, you are not capable of
> holding a sensible discussion and there's no point in continuing.

The discussion is superfluous because we have constructors instead
of designated initializers.

Juha Nieminen

unread,
Nov 10, 2020, 8:13:41 AM11/10/20
to
In fact, designated initializer can be combined with constructors (or with
any functions for that matter) in order to, effectively, get named function
parameters where all of them can have default values and you can override
any of them with a different value.

In other words, you could have something along the lines of:

struct MyClassParams
{
int firstValue = 0, secondValue = 10;
float someFloat = 0.0, anotherFloat = 5.0;
const char* name = nullptr;
};

MyClass::MyClass(const MyClassParams& params) { ... }

You could then, ostensibly, instantiate the class like:

MyClass obj({ .secondValue = 15, .name = "Fancy Name" });

(If there are any mandatory parameters, they could be specified as
their own function parameters before that MyClassParams parameter.)

Jorgen Grahn

unread,
Nov 10, 2020, 4:41:33 PM11/10/20
to
I see you're not interested in a serious discussion.

Brian Wood

unread,
Nov 11, 2020, 8:21:29 AM11/11/20
to
I don't understand why you say that. I've often found
your posts to be thoughtful and interesting.


Brian
Ebenezer Enterprises
https://webEbenezer.net

Jorgen Grahn

unread,
Nov 18, 2020, 2:17:08 AM11/18/20
to
I should explain that my "you" meant Juha, not everyone. And I didn't
mean Juha is /never/ interested in a serious discussion, just this
time.

(That this subthread was driven by C. Hanné surely didn't help.)
0 new messages