Discussion:
Yet another inconsitent behavior in C++
(too old to reply)
a***@gmail.com
2015-03-15 13:41:39 UTC
Permalink
Guys,
Taken from stackoverflow, but actually I came up against identical problem
yesterday and was puzzled as to why my code doesn't compile:

First:

int k[] ={1,2,3,4,5};


Second:

struct slk{
int k[] ={1,2,3,4,5};};


First compiles, second doesn't saying that there is too many initializers.
Surely when looking at it soberly those two lines of code are identical and
one being in a global namespace and second being in a namespace of struct
shouldn't have any impact on compiler behavior. Why is it that in First
example compiler can deduce the size and in second it either cannot or
won't do it? AFAIC, First notion is more preferable from the point of view
of being easier modifiable, avoiding silly mistakes when providing explicit
size of array, heck, even Bjarne in either one of his books of papers
suggest the first option, in the same vein as this example:
enum a { one = 1, two, three};
instead:
enum a {one = 1, two = 2, three = 3};

Why is second option not allowed?!? It goes against every logical instinct.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-15 16:52:44 UTC
Permalink
Because the second one is a completely different statement.

In the first case, you are defining a *variable*, a specific memory object
with a specific location. In the second case, you are defining a *type*,
which can be *instantiated* any number of times in any number of places.

Types have different rules. In particular, member initializers (what you're
doing when you initialize a member like that) have different rules from
variable initializers. Member initializers are shorthand for this:

struct slk
{
slk() : k{1,2,3,4,5} {}
int k[];
};

See the problem? Member initializers are a shorthand for writing
*constructor* member initializers. And constructors cannot decide what the
size of members are.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 17:43:21 UTC
Permalink
Surely constructor can count those initializers and use that number as a
size. That seems pretty obvious to me.
Post by Nicol Bolas
Because the second one is a completely different statement.
In the first case, you are defining a *variable*, a specific memory
object with a specific location. In the second case, you are defining a
*type*, which can be *instantiated* any number of times in any number of
places.
Types have different rules. In particular, member initializers (what
you're doing when you initialize a member like that) have different rules
struct slk
{
slk() : k{1,2,3,4,5} {}
int k[];
};
See the problem? Member initializers are a shorthand for writing
*constructor* member initializers. And constructors cannot decide what
the size of members are.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 17:46:40 UTC
Permalink
Post by a***@gmail.com
Surely constructor can count those initializers and use that number as a
size. That seems pretty obvious to me.
struct slk{
slk() {}
slk(int i) : k{i,7} ()
int k[] ={1,2,3,4,5};
};

Now which one does it choose?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 17:55:09 UTC
Permalink
It counts how many initializers is in between { }, puts that number in
array and goes from there. I'm sorry but to me this is simply illogical
behavior.
Post by a***@gmail.com
Post by a***@gmail.com
Surely constructor can count those initializers and use that number as a
size. That seems pretty obvious to me.
struct slk{
slk() {}
slk(int i) : k{i,7} ()
int k[] ={1,2,3,4,5};
};
Now which one does it choose?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 17:56:43 UTC
Permalink
Don't want to be picky but when you say:
slk(int i) : k{i,7} ()
you really mean:
slk(int i) : k{i,7} {}
right?
Post by a***@gmail.com
It counts how many initializers is in between { }, puts that number in
array and goes from there. I'm sorry but to me this is simply illogical
behavior.
Post by a***@gmail.com
Post by a***@gmail.com
Surely constructor can count those initializers and use that number as
a
Post by a***@gmail.com
size. That seems pretty obvious to me.
struct slk{
slk() {}
slk(int i) : k{i,7} ()
int k[] ={1,2,3,4,5};
};
Now which one does it choose?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-15 17:57:03 UTC
Permalink
Post by Thiago Macieira
slk(int i) : k{i,7} ()
slk(int i) : k{i,7} {}
right?
http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3897.html
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 18:04:25 UTC
Permalink
Mind to elaborate?
Either he is using feature not from current standard or he is using feature
which has little chance of being implemented in future standard, correct?
Post by Ville Voutilainen
Post by Thiago Macieira
slk(int i) : k{i,7} ()
slk(int i) : k{i,7} {}
right?
http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3897.html
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-15 18:05:15 UTC
Permalink
Post by a***@gmail.com
Mind to elaborate?
Either he is using feature not from current standard or he is using feature
which has little chance of being implemented in future standard, correct?
The reasons why auto-typed members are not doable apply equally well
to deducing an extent of an array member from that member's initializer.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 18:08:52 UTC
Permalink
is this code correct:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } ()
int k[] = { 1, 2, 3, 4, 5 };
};
Post by a***@gmail.com
Post by a***@gmail.com
Mind to elaborate?
Either he is using feature not from current standard or he is using
feature
Post by a***@gmail.com
which has little chance of being implemented in future standard,
correct?
The reasons why auto-typed members are not doable apply equally well
to deducing an extent of an array member from that member's initializer.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Daniel Krügler
2015-03-15 19:05:47 UTC
Permalink
Post by a***@gmail.com
struct slk{
slk() {}
slk(int i) : k{ i, 7 } ()
int k[] = { 1, 2, 3, 4, 5 };
};
No. It would make sizeof(slk) different depending on which constructor you
called. C++ doesn't support that.
I don't think that Arthur did suggest this outcome. According to his
statement in

https://groups.google.com/a/isocpp.org/d/msg/std-discussion/lzcGWLDHxr4/Hao4DRD4DpMJ

it seems that he expected that k would always have the same length of
five elements regardless of the actually chosen constructor.

- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 19:14:24 UTC
Permalink
Post by Daniel Krügler
it seems that he expected that k would always have the same length of
five elements regardless of the actually chosen constructor.
Even if no constructor ever initialised with that declaration?

struct S {
int k[] = { 1, 2, 3 };
S() : k{4, 5} {}
};
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Daniel Krügler
2015-03-15 19:15:58 UTC
Permalink
Post by Thiago Macieira
Post by Daniel Krügler
it seems that he expected that k would always have the same length of
five elements regardless of the actually chosen constructor.
Even if no constructor ever initialised with that declaration?
struct S {
int k[] = { 1, 2, 3 };
S() : k{4, 5} {}
};
That is my understanding (but it seems better to have the OP respond
to this question).

- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 19:25:37 UTC
Permalink
Yes, even if no ctor ever initialized, the size of k array is that size
defined in class declaration. If it says:
int k[] = {0,1,2};
then that size of this array is *always* three. I seriously don't see
anything strange about it. Nor unconventional. You define this array in a
class, you init it. And in other constructors you can re-init it to your
likings. What is wrong with that. But the point, the main point is the one
where I provide identical examples and one compiles and one doesn't (which
is illogical), because in one size of array is explicitly stated and in the
other is not. This is wrong. This is illogical. This is hurtful.
Post by Thiago Macieira
Post by Daniel Krügler
it seems that he expected that k would always have the same length of
five elements regardless of the actually chosen constructor.
Even if no constructor ever initialised with that declaration?
struct S {
int k[] = { 1, 2, 3 };
S() : k{4, 5} {}
};
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 19:29:24 UTC
Permalink
Post by a***@gmail.com
Yes, even if no ctor ever initialized, the size of k array is that size
int k[] = {0,1,2};
then that size of this array is *always* three. I seriously don't see
anything strange about it. Nor unconventional. You define this array in a
class, you init it. And in other constructors you can re-init it to your
likings. What is wrong with that. But the point, the main point is the one
where I provide identical examples and one compiles and one doesn't (which
is illogical), because in one size of array is explicitly stated and in the
other is not. This is wrong. This is illogical. This is hurtful.
I understand what you want, but that's not what the standard currently
requires.

The standard requires that you decompose

struct S {
int k[] = { 1, 2, 3 };
S() {}
};

to:

struct S {
int k[];
S() k{1, 2, 3} {}
};

For the first one to do what you've requested, we need those auto members
proposal.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 19:35:28 UTC
Permalink
Then the behavior described by standard is illogical, wrong and hurtful. I
really can't see it differently.
I would be less inclined to be irritated by this behavior if this didn't
compile:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};

but it does. It baffles me and it irritates me.
Post by a***@gmail.com
Post by a***@gmail.com
Yes, even if no ctor ever initialized, the size of k array is that size
int k[] = {0,1,2};
then that size of this array is *always* three. I seriously don't see
anything strange about it. Nor unconventional. You define this array in
a
Post by a***@gmail.com
class, you init it. And in other constructors you can re-init it to your
likings. What is wrong with that. But the point, the main point is the
one
Post by a***@gmail.com
where I provide identical examples and one compiles and one doesn't
(which
Post by a***@gmail.com
is illogical), because in one size of array is explicitly stated and in
the
Post by a***@gmail.com
other is not. This is wrong. This is illogical. This is hurtful.
I understand what you want, but that's not what the standard currently
requires.
The standard requires that you decompose
struct S {
int k[] = { 1, 2, 3 };
S() {}
};
struct S {
int k[];
S() k{1, 2, 3} {}
};
For the first one to do what you've requested, we need those auto members
proposal.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 19:41:32 UTC
Permalink
Post by a***@gmail.com
Then the behavior described by standard is illogical, wrong and hurtful. I
really can't see it differently.
I would be less inclined to be irritated by this behavior if this didn't
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
but it does. It baffles me and it irritates me.
Why should this not compile?

struct slk{
slk(int i) : k{ i, 7 } {}
int k[5] ;
};
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 19:44:13 UTC
Permalink
That's not the example I've posted. In my example array is inited with 5
literals. Compiler can easily count it. and place that number in array size.
Post by Thiago Macieira
Post by a***@gmail.com
Then the behavior described by standard is illogical, wrong and hurtful.
I
Post by a***@gmail.com
really can't see it differently.
I would be less inclined to be irritated by this behavior if this didn't
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets
into
Post by a***@gmail.com
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
but it does. It baffles me and it irritates me.
Why should this not compile?
struct slk{
slk(int i) : k{ i, 7 } {}
int k[5] ;
};
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 19:53:58 UTC
Permalink
Post by a***@gmail.com
That's not the example I've posted. In my example array is inited with 5
literals. Compiler can easily count it. and place that number in array size.
I know it isn't the same example. I just removed the superfluous part.
Post by a***@gmail.com
Post by Thiago Macieira
Why should this not compile?
struct slk{
slk(int i) : k{ i, 7 } {}
int k[5] ;
};
The above should compile. Then let's add a new constructor:

struct slk{
slk() : k{1, 2, 3, 4, 5} {}
slk(int i) : k{ i, 7 } {}
int k[5] ;
};

And now let's modify the example above to move the array initialisation:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[5] = {1, 2, 3, 4, 5};
};

Please explain why you think any of the examples above should not compile.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 19:59:03 UTC
Permalink
They should compile. I don't see reason why they shouldn't. I also don't
see reason why this shouldn't compile:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = {1, 2, 3, 4, 5};
};

Please explain to me why do you think compiler cannot count the number of
initializers and use this number as a size of k array?
It (the compiler) does it here:

int k[] = {1, 2, 3, 4, 5};
why cannot it do it here:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = {1, 2, 3, 4, 5};
};
Post by Thiago Macieira
Post by a***@gmail.com
That's not the example I've posted. In my example array is inited with 5
literals. Compiler can easily count it. and place that number in array
size.
I know it isn't the same example. I just removed the superfluous part.
Post by a***@gmail.com
Post by Thiago Macieira
Why should this not compile?
struct slk{
slk(int i) : k{ i, 7 } {}
int k[5] ;
};
struct slk{
slk() : k{1, 2, 3, 4, 5} {}
slk(int i) : k{ i, 7 } {}
int k[5] ;
};
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[5] = {1, 2, 3, 4, 5};
};
Please explain why you think any of the examples above should not compile.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 20:46:51 UTC
Permalink
Post by a***@gmail.com
They should compile. I don't see reason why they shouldn't. I also don't
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = {1, 2, 3, 4, 5};
};
Please explain to me why do you think compiler cannot count the number of
initializers and use this number as a size of k array?
int k[] = {1, 2, 3, 4, 5};
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = {1, 2, 3, 4, 5};
};
We've already explained it. The above is currently required by the standard to
be equivalent to:

struct slk{
slk() : k{1, 2, 3, 4, 5} {}
slk(int i) : k{ i, 7 } {}
int k[];
};

Please note that the above triggers the "empty array trailing member"
extension, so you could do:

slk *s = new (malloc(5 * sizeof(int))) slk;
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Dinka Ranns
2015-03-15 19:57:10 UTC
Permalink
The intent is not to allow an array of unknown bound as a non static data
member. If one wants such a feature, one should write a proposal.

However, the standard doesn't explicitly disallow what Arthur wants, and it
can be read to allow for an array of unknown bound as a non static data
member, provided an initializer exists. I'll ping core about this.
Post by a***@gmail.com
That's not the example I've posted. In my example array is inited with 5
literals. Compiler can easily count it. and place that number in array size.
Post by a***@gmail.com
Post by a***@gmail.com
Then the behavior described by standard is illogical, wrong and
hurtful. I
Post by a***@gmail.com
really can't see it differently.
I would be less inclined to be irritated by this behavior if this
didn't
Post by a***@gmail.com
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets
into
Post by a***@gmail.com
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
but it does. It baffles me and it irritates me.
Why should this not compile?
struct slk{
slk(int i) : k{ i, 7 } {}
int k[5] ;
};
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Chris Hallock
2015-03-16 19:20:17 UTC
Permalink
Post by Dinka Ranns
However, the standard doesn't explicitly disallow what Arthur wants, and
it can be read to allow for an array of unknown bound as a non static data
member, provided an initializer exists.
Actually, as Richard pointed out to me in an earlier discussion
<https://groups.google.com/a/isocpp.org/d/msg/std-discussion/CIhT96l0gB8/02TOE8tkvLsJ>,
the standard does clearly prohibit this, in 8.3.4/3: "An array bound may
also be omitted when the declarator is followed by an *initializer *(8.5)."
NSDMIs are not *initializers*. They are *brace-or-equal-initializers*
instead. An *initializer *can consist of a *brace-or-equal-initializer* but
not the other way around.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Dinka Ranns
2015-03-16 20:08:16 UTC
Permalink
Post by Chris Hallock
Post by Dinka Ranns
However, the standard doesn't explicitly disallow what Arthur wants, and
it can be read to allow for an array of unknown bound as a non static data
member, provided an initializer exists.
Actually, as Richard pointed out to me in an earlier discussion
<https://groups.google.com/a/isocpp.org/d/msg/std-discussion/CIhT96l0gB8/02TOE8tkvLsJ>,
the standard does clearly prohibit this, in 8.3.4/3: "An array bound may
also be omitted when the declarator is followed by an *initializer *(8.5)."
NSDMIs are not *initializers*. They are *brace-or-equal-initializers*
instead. An *initializer *can consist of a *brace-or-equal-initializer*
but not the other way around.
yes, Richard has since pointed out the same thing to me... :)

--
Post by Chris Hallock
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Johannes Schaub' via ISO C++ Standard - Discussion
2015-10-04 12:40:48 UTC
Permalink
Post by Dinka Ranns
However, the standard doesn't explicitly disallow what Arthur wants, and
it can be read to allow for an array of unknown bound as a non static data
member, provided an initializer exists.
Actually, as Richard pointed out to me in an earlier discussion, the
standard does clearly prohibit this, in 8.3.4/3: "An array bound may also be
omitted when the declarator is followed by an initializer (8.5)." NSDMIs are
not initializers. They are brace-or-equal-initializers instead. An
initializer can consist of a brace-or-equal-initializer but not the other
way around.
The same is true about qualified-id vs "nested-name-specifier
unqualified-id". But still, statements about "qualified-id" apply to
situations were we see only a "nested-name-specifier unqualified-id"
or "nested-name-specifier identifier".

For example: "If the qualified-id in a typename-specifier does not
denote a type, the program is ill-formed." at 14.6p3.

So I wouldn't say the Standard "clearly prohibits" that based on
syntactical nuances that the Standard has no clear concept of.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Chris Hallock
2015-10-04 18:38:16 UTC
Permalink
Post by Chris Hallock
Post by Dinka Ranns
However, the standard doesn't explicitly disallow what Arthur wants,
and
Post by Dinka Ranns
it can be read to allow for an array of unknown bound as a non static
data
Post by Dinka Ranns
member, provided an initializer exists.
Actually, as Richard pointed out to me in an earlier discussion, the
standard does clearly prohibit this, in 8.3.4/3: "An array bound may
also be
omitted when the declarator is followed by an initializer (8.5)." NSDMIs
are
not initializers. They are brace-or-equal-initializers instead. An
initializer can consist of a brace-or-equal-initializer but not the
other
way around.
The same is true about qualified-id vs "nested-name-specifier
unqualified-id". But still, statements about "qualified-id" apply to
situations were we see only a "nested-name-specifier unqualified-id"
or "nested-name-specifier identifier".
For example: "If the qualified-id in a typename-specifier does not
denote a type, the program is ill-formed." at 14.6p3.
So I wouldn't say the Standard "clearly prohibits" that based on
syntactical nuances that the Standard has no clear concept of.
That would be a great counter-example, except that 5.1.1/9 says:

"A *nested-name-specifier* that denotes a class, optionally followed by the
keyword template (14.2), and then followed by the name of a member of
either that class (9.2) or one of its base classes (Clause 10), is a
*qualified-id* [...]"

Which is one of those unfortunate cases where the grammar notations don't
fully describe the grammar.

Still, I concede that claiming that the Standard "clearly" prohibits
deduced array bounds for member arrays is overstating the clarity of the
Standard. Ideally, that scenario would be mentioned in a note or example.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Johannes Schaub' via ISO C++ Standard - Discussion
2015-10-04 19:33:03 UTC
Permalink
This disambiguity is resooved by referring to the nonterminal in italic and
to the defined term in nonitalic. Yet the example I mentioned does refer to
the grammar nonterminal since the use is in italic.
Post by 'Johannes Schaub' via ISO C++ Standard - Discussion
Post by Dinka Ranns
However, the standard doesn't explicitly disallow what Arthur wants, and
it can be read to allow for an array of unknown bound as a non static data
member, provided an initializer exists.
Actually, as Richard pointed out to me in an earlier discussion, the
standard does clearly prohibit this, in 8.3.4/3: "An array bound may also be
omitted when the declarator is followed by an initializer (8.5)." NSDMIs are
not initializers. They are brace-or-equal-initializers instead. An
initializer can consist of a brace-or-equal-initializer but not the other
way around.
The same is true about qualified-id vs "nested-name-specifier
unqualified-id". But still, statements about "qualified-id" apply to
situations were we see only a "nested-name-specifier unqualified-id"
or "nested-name-specifier identifier".
For example: "If the qualified-id in a typename-specifier does not
denote a type, the program is ill-formed." at 14.6p3.
So I wouldn't say the Standard "clearly prohibits" that based on
syntactical nuances that the Standard has no clear concept of.
"A nested-name-specifier that denotes a class, optionally followed by the
keyword template (14.2), and then followed by the name of a member of
either that class (9.2) or one of its base classes (Clause 10), is a
qualified-id [...]"
Which is one of those unfortunate cases where the grammar notations don't
fully describe the grammar.
Still, I concede that claiming that the Standard "clearly" prohibits
deduced array bounds for member arrays is overstating the clarity of the
Standard. Ideally, that scenario would be mentioned in a note or example.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Daniel Krügler
2015-03-15 20:24:32 UTC
Permalink
Post by a***@gmail.com
Then the behavior described by standard is illogical, wrong and hurtful. I
really can't see it differently.
I would be less inclined to be irritated by this behavior if this didn't
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
but it does. It baffles me and it irritates me.
I have some sympathies regarding fixing this bafflement, but such a
change of rules needs to be done carefully. Especially it shouldn't
have negative impact on the current "lazy evaluation" of
brace-or-equal-initializers. Currently the Standard says that the
brace-or-equal-initializers are not considered unless used, so
especially in type-dependent situations this is a valueable guarantee.
Consider the following example:

template<class T>
struct X
{
T array[3] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};

struct S
{
};

int main() {
X<S> x(S{});
}

This is currently well-formed, albeit S cannot be initialized by
integer values. If I understand your proposal correctly, a compiler
would *always* be required to evaluate the initializer in this
situation regardless of the chosen constructor:

template<class T>
struct X
{
T array[] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};

because it is required to analyze the initializer-expression to deduce
the member array size. I suspect that for the general case this means
that the compiler has to inspect the full-expression during
compile-time, because such initializers can be arbitrary complex and I
doubt that for a general case a compiler can just "count" the elements
without evaluating the initializer.

It may be possible to find wording that ensures that this required
analysis only happens for members that are arrays of unknown bounds,
but what I want to say here is that this wording really has to be
provided to prevent unwanted non-lazy evaluations in other situations.

- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-16 10:10:44 UTC
Permalink
Daniel, thank you for your input. Agree with what you've said and that is
basically on the lines of my thinking. Could you perhaps think of any
example in which size of that array would be difficult (for compiler) to
deduce from the initializer list that is.

struct slk
{
int k[] = {1, 2, 3, 4, 5}; //this place, can you think about any
example to make that size of array tricky for compiler to deduce? I can't.
};
Post by Daniel Krügler
Post by a***@gmail.com
Then the behavior described by standard is illogical, wrong and hurtful.
I
Post by a***@gmail.com
really can't see it differently.
I would be less inclined to be irritated by this behavior if this didn't
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets
into
Post by a***@gmail.com
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
but it does. It baffles me and it irritates me.
I have some sympathies regarding fixing this bafflement, but such a
change of rules needs to be done carefully. Especially it shouldn't
have negative impact on the current "lazy evaluation" of
brace-or-equal-initializers. Currently the Standard says that the
brace-or-equal-initializers are not considered unless used, so
especially in type-dependent situations this is a valueable guarantee.
template<class T>
struct X
{
T array[3] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};
struct S
{
};
int main() {
X<S> x(S{});
}
This is currently well-formed, albeit S cannot be initialized by
integer values. If I understand your proposal correctly, a compiler
would *always* be required to evaluate the initializer in this
template<class T>
struct X
{
T array[] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};
because it is required to analyze the initializer-expression to deduce
the member array size. I suspect that for the general case this means
that the compiler has to inspect the full-expression during
compile-time, because such initializers can be arbitrary complex and I
doubt that for a general case a compiler can just "count" the elements
without evaluating the initializer.
It may be possible to find wording that ensures that this required
analysis only happens for members that are arrays of unknown bounds,
but what I want to say here is that this wording really has to be
provided to prevent unwanted non-lazy evaluations in other situations.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-03-16 18:17:21 UTC
Permalink
Post by a***@gmail.com
Daniel, thank you for your input. Agree with what you've said and that is
basically on the lines of my thinking. Could you perhaps think of any
example in which size of that array would be difficult (for compiler) to
deduce from the initializer list that is.
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
char a[] = { T<sizeof(X)>::a<0, 0>(0) };
};

What's the bound of X::a, 1 or 2? (Note that X is a complete type in this
context, because the initializer is handled as if it appeared in a
constructor, so sizeof(X) is valid.)

struct slk
Post by a***@gmail.com
{
int k[] = {1, 2, 3, 4, 5}; //this place, can you think about any
example to make that size of array tricky for compiler to deduce? I can't.
};
Post by a***@gmail.com
Post by a***@gmail.com
Then the behavior described by standard is illogical, wrong and
hurtful. I
Post by a***@gmail.com
really can't see it differently.
I would be less inclined to be irritated by this behavior if this
didn't
Post by a***@gmail.com
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets
into
Post by a***@gmail.com
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
but it does. It baffles me and it irritates me.
I have some sympathies regarding fixing this bafflement, but such a
change of rules needs to be done carefully. Especially it shouldn't
have negative impact on the current "lazy evaluation" of
brace-or-equal-initializers. Currently the Standard says that the
brace-or-equal-initializers are not considered unless used, so
especially in type-dependent situations this is a valueable guarantee.
template<class T>
struct X
{
T array[3] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};
struct S
{
};
int main() {
X<S> x(S{});
}
This is currently well-formed, albeit S cannot be initialized by
integer values. If I understand your proposal correctly, a compiler
would *always* be required to evaluate the initializer in this
template<class T>
struct X
{
T array[] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};
because it is required to analyze the initializer-expression to deduce
the member array size. I suspect that for the general case this means
that the compiler has to inspect the full-expression during
compile-time, because such initializers can be arbitrary complex and I
doubt that for a general case a compiler can just "count" the elements
without evaluating the initializer.
It may be possible to find wording that ensures that this required
analysis only happens for members that are arrays of unknown bounds,
but what I want to say here is that this wording really has to be
provided to prevent unwanted non-lazy evaluations in other situations.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-16 18:28:15 UTC
Permalink
Post by Richard Smith
Post by a***@gmail.com
Daniel, thank you for your input. Agree with what you've said and that is
basically on the lines of my thinking. Could you perhaps think of any
example in which size of that array would be difficult (for compiler) to
deduce from the initializer list that is.
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
char a[] = { T<sizeof(X)>::a<0, 0>(0) };
};
What's the bound of X::a, 1 or 2? (Note that X is a complete type in this
context, because the initializer is handled as if it appeared in a
constructor, so sizeof(X) is valid.)
Except X can't be complete before it knows its size, which it can't know before
it uses the initializer for a, which it can't do because that requires
knowing the
size, and thus the merry-go-round spins until the compiler possibly
says "oh, snap, stop". :)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-16 21:29:05 UTC
Permalink
Post by Ville Voutilainen
Post by Richard Smith
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
char a[] = { T<sizeof(X)>::a<0, 0>(0) };
};
What's the bound of X::a, 1 or 2? (Note that X is a complete type in this
context, because the initializer is handled as if it appeared in a
constructor, so sizeof(X) is valid.)
Except X can't be complete before it knows its size, which it can't know
before it uses the initializer for a, which it can't do because that
requires knowing the
size, and thus the merry-go-round spins until the compiler possibly
says "oh, snap, stop".
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
X();
char a[];;
};

X::X() : a{ T<sizeof(X)>::a<0, 0>(0) }
{}

Are you saying that X isn't complete in the X::X constructor declaration?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-16 21:54:53 UTC
Permalink
Post by Richard Smith
Post by Ville Voutilainen
Post by Richard Smith
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
char a[] = { T<sizeof(X)>::a<0, 0>(0) };
};
What's the bound of X::a, 1 or 2? (Note that X is a complete type in this
context, because the initializer is handled as if it appeared in a
constructor, so sizeof(X) is valid.)
Except X can't be complete before it knows its size, which it can't know
before it uses the initializer for a, which it can't do because that
requires knowing the
size, and thus the merry-go-round spins until the compiler possibly
says "oh, snap, stop".
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
X();
char a[];;
};
X::X() : a{ T<sizeof(X)>::a<0, 0>(0) }
{}
Are you saying that X isn't complete in the X::X constructor declaration?
No. The question is whether the class can be complete before its size
is known. Last I checked, the answer to that question is no.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-16 22:03:48 UTC
Permalink
Post by Ville Voutilainen
Post by Richard Smith
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
X();
char a[];;
};
X::X() : a{ T<sizeof(X)>::a<0, 0>(0) }
{}
Are you saying that X isn't complete in the X::X constructor declaration?
No. The question is whether the class can be complete before its size
is known. Last I checked, the answer to that question is no.
Agreed, but I'm missing how that is relevant to the discussion.

Unless you're talking about the case in which the compiler must evaluate the
nsdmi initialiser inside the class.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-03-16 22:05:49 UTC
Permalink
Post by Richard Smith
Post by Ville Voutilainen
Post by Richard Smith
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
char a[] = { T<sizeof(X)>::a<0, 0>(0) };
};
What's the bound of X::a, 1 or 2? (Note that X is a complete type in
this
Post by Ville Voutilainen
Post by Richard Smith
context, because the initializer is handled as if it appeared in a
constructor, so sizeof(X) is valid.)
Except X can't be complete before it knows its size, which it can't know
before it uses the initializer for a, which it can't do because that
requires knowing the
size, and thus the merry-go-round spins until the compiler possibly
says "oh, snap, stop".
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
X();
char a[];;
};
X::X() : a{ T<sizeof(X)>::a<0, 0>(0) }
{}
Are you saying that X isn't complete in the X::X constructor declaration?
That's ill-formed because X::a has an incomplete type. X would be complete
in the X::X constructor, but the program was ill-formed before we got
there. (And the example I gave is ill-formed for essentially the same
reason.)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-16 23:11:19 UTC
Permalink
Post by Richard Smith
Post by Richard Smith
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
X();
char a[];;
};
X::X() : a{ T<sizeof(X)>::a<0, 0>(0) }
{}
Are you saying that X isn't complete in the X::X constructor declaration?
That's ill-formed because X::a has an incomplete type. X would be complete
in the X::X constructor, but the program was ill-formed before we got
there. (And the example I gave is ill-formed for essentially the same
reason.)
Ah, I see what you mean.

I tested it with Clang and it accepted. It triggered the extension for flexible
trailing types and assumes that the caller allocated enough space for the
elements used in the array.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-03-16 23:37:45 UTC
Permalink
Post by Thiago Macieira
Post by Richard Smith
Post by Richard Smith
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
X();
char a[];;
};
X::X() : a{ T<sizeof(X)>::a<0, 0>(0) }
{}
Are you saying that X isn't complete in the X::X constructor
declaration?
Post by Richard Smith
That's ill-formed because X::a has an incomplete type. X would be
complete
Post by Richard Smith
in the X::X constructor, but the program was ill-formed before we got
there. (And the example I gave is ill-formed for essentially the same
reason.)
Ah, I see what you mean.
I tested it with Clang and it accepted. It triggered the extension for flexible
trailing types and assumes that the caller allocated enough space for the
elements used in the array.
Yep, Clang accepts C99 flexible array members in C++ as a GNU extension;
use -std=c++11 -pedantic-errors to compile in strictly-conforming mode.
(That mode also rejects your double-semicolon...)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Faisal Vali
2015-03-17 00:12:50 UTC
Permalink
Post by Richard Smith
Post by a***@gmail.com
Daniel, thank you for your input. Agree with what you've said and that is
basically on the lines of my thinking. Could you perhaps think of any
example in which size of that array would be difficult (for compiler) to
deduce from the initializer list that is.
template<int> struct T;
template<> struct T<1> { template<int,int> char a(int); };
template<> struct T<2> { static int a; };
struct X {
char a[] = { T<sizeof(X)>::a<0, 0>(0) };
};
What's the bound of X::a, 1 or 2? (Note that X is a complete type in this
context, because the initializer is handled as if it appeared in a
constructor, so sizeof(X) is valid.)
Post by a***@gmail.com
struct slk
{
int k[] = {1, 2, 3, 4, 5}; //this place, can you think about any
example to make that size of array tricky for compiler to deduce? I can't.
};
If someone really had compelling use cases for declaring non-static
data members with the initial array bound omitted, one could craft a
"scheme" to make it work.

For example:
If we agree that in order to determine the size of the class prior to
parsing the default initializers, the only information we need from
the initializer list is the number of elements in it, and we agree
that whatever we determine to be the number during the initial lexing
(tokenizing) for each of those unknown bounds should be the same
number when we parse it at the end of the class definition (i.e. the
size of the class has been sealed), then:
- the number of elements in the initializer-list during initial
lexing can be determined by the number of commas un-enclosed within
parens or additional braces within the outer-most initializer-list
- at the closing brace of the class definition, that number is used
to compute the size of the class
- when parsing the default initializers of the class, if the size of
the omitted array bound is different from the initial count, a helpful
error could be emitted

So if the compiler errors out, you could re-write the default
initializer as : { (T<sizeof(X)>::a < 0 ), 0 > (0) }.

I'm certainly not saying this is a road you should try and take us
down - it seems not entirely without peril, and the reward seems
unclear ...
Post by Richard Smith
Post by a***@gmail.com
Post by Daniel Krügler
Post by a***@gmail.com
Then the behavior described by standard is illogical, wrong and hurtful. I
really can't see it differently.
I would be less inclined to be irritated by this behavior if this didn't
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
but it does. It baffles me and it irritates me.
I have some sympathies regarding fixing this bafflement, but such a
change of rules needs to be done carefully. Especially it shouldn't
have negative impact on the current "lazy evaluation" of
brace-or-equal-initializers. Currently the Standard says that the
brace-or-equal-initializers are not considered unless used, so
especially in type-dependent situations this is a valueable guarantee.
template<class T>
struct X
{
T array[3] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};
struct S
{
};
int main() {
X<S> x(S{});
}
This is currently well-formed, albeit S cannot be initialized by
integer values. If I understand your proposal correctly, a compiler
would *always* be required to evaluate the initializer in this
template<class T>
struct X
{
T array[] = {1, 2, 3};
explicit X(T val) : array{val, val, val} {}
X() = default;
};
because it is required to analyze the initializer-expression to deduce
the member array size. I suspect that for the general case this means
that the compiler has to inspect the full-expression during
compile-time, because such initializers can be arbitrary complex and I
doubt that for a general case a compiler can just "count" the elements
without evaluating the initializer.
It may be possible to find wording that ensures that this required
analysis only happens for members that are arrays of unknown bounds,
but what I want to say here is that this wording really has to be
provided to prevent unwanted non-lazy evaluations in other situations.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 19:18:01 UTC
Permalink
Exactly what Daniel said.
Post by Daniel Krügler
Post by a***@gmail.com
struct slk{
slk() {}
slk(int i) : k{ i, 7 } ()
int k[] = { 1, 2, 3, 4, 5 };
};
No. It would make sizeof(slk) different depending on which constructor
you
called. C++ doesn't support that.
I don't think that Arthur did suggest this outcome. According to his
statement in
https://groups.google.com/a/isocpp.org/d/msg/std-discussion/lzcGWLDHxr4/Hao4DRD4DpMJ
it seems that he expected that k would always have the same length of
five elements regardless of the actually chosen constructor.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 18:03:36 UTC
Permalink
Post by a***@gmail.com
It counts how many initializers is in between { }, puts that number in
array and goes from there. I'm sorry but to me this is simply illogical
behavior.
Right, so you're saying it's an array of 2 entries. Why should the other
constructor initialise it with 5?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 18:08:08 UTC
Permalink
For the same reason why:

struct X
{
int a = 0;
X(int val):a(val)
{}
};
Default ctor will init a to zero, converting ctor will init a to whatever
the val is.
Post by Thiago Macieira
Post by a***@gmail.com
It counts how many initializers is in between { }, puts that number in
array and goes from there. I'm sorry but to me this is simply illogical
behavior.
Right, so you're saying it's an array of 2 entries. Why should the other
constructor initialise it with 5?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 18:10:01 UTC
Permalink
I'm not saying that this is array of size two. This is always array of size
5. Always.
Post by Thiago Macieira
Post by a***@gmail.com
It counts how many initializers is in between { }, puts that number in
array and goes from there. I'm sorry but to me this is simply illogical
behavior.
Right, so you're saying it's an array of 2 entries. Why should the other
constructor initialise it with 5?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-15 18:11:16 UTC
Permalink
Post by a***@gmail.com
I'm not saying that this is array of size two. This is always array of size
5. Always.
Go implement your proposal and come back when you've done so.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 18:19:46 UTC
Permalink
Could you please answer to my question about code posted by thiago?
Because like I've said either he is using feature not from current standard
or he is using feature which has little chance of being implemented in
future standard. Which either way seems weird.
Post by Ville Voutilainen
Post by a***@gmail.com
I'm not saying that this is array of size two. This is always array of
size
Post by a***@gmail.com
5. Always.
Go implement your proposal and come back when you've done so.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 18:26:22 UTC
Permalink
@Thiago:
Why this compiles then:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
and this doesn't:
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = { 1, 2, 3, 4, 5 };
};

According to your argument compiler wouldn't know which size to choose yet
it has no problem with this code if the size is supplied which I have to
stress it, should be easily done by compiler. It simply doesn't make sense
and is against any logic.
Post by a***@gmail.com
Could you please answer to my question about code posted by thiago?
Because like I've said either he is using feature not from current
standard or he is using feature which has little chance of being
implemented in future standard. Which either way seems weird.
Post by Ville Voutilainen
Post by a***@gmail.com
I'm not saying that this is array of size two. This is always array of
size
Post by a***@gmail.com
5. Always.
Go implement your proposal and come back when you've done so.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 19:03:49 UTC
Permalink
Post by a***@gmail.com
Could you please answer to my question about code posted by thiago?
Because like I've said either he is using feature not from current standard
or he is using feature which has little chance of being implemented in
future standard. Which either way seems weird.
Ok, let me change it to make it more explicit:


struct slk{
slk() {}
slk(int i) : k{ i, 9, 8, 7, 6 } {}
int k[] = { 1, 2 };
};

What is the size of the k array?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 19:16:08 UTC
Permalink
But now after you've changed example, you are trying to initialize array of
size two with five elements which is incorrect and I would never expect
that.

Guys, are you seriously not seeing anything wrong with the fact that this
compiles:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};

and this doesn't:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = { 1, 2, 3, 4, 5 };
};

even though the only difference between those two examples is that in one
size of array is explicitly stated and in the second size of array to be
expected to be deduced by compiler which need I remind you, compiler
already can do it and does it in other scenarios.
Seriously guys.
Post by a***@gmail.com
Post by a***@gmail.com
Could you please answer to my question about code posted by thiago?
Because like I've said either he is using feature not from current
standard
Post by a***@gmail.com
or he is using feature which has little chance of being implemented in
future standard. Which either way seems weird.
struct slk{
slk() {}
slk(int i) : k{ i, 9, 8, 7, 6 } {}
int k[] = { 1, 2 };
};
What is the size of the k array?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 19:24:02 UTC
Permalink
Post by a***@gmail.com
Guys, are you seriously not seeing anything wrong with the fact that this
No.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-15 19:57:47 UTC
Permalink
Post by a***@gmail.com
But now after you've changed example, you are trying to initialize array
of size two with five elements which is incorrect and I would never expect
that.
Guys, are you seriously not seeing anything wrong with the fact that this
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = { 1, 2, 3, 4, 5 };
};
even though the only difference between those two examples is that in one
size of array is explicitly stated and in the second size of array to be
expected to be deduced by compiler which need I remind you, compiler
already can do it and does it in other scenarios.
Except that those "other scenarios" are very different. Namely, the object
is initialized in *exactly* one place.

In this case, the object is being initialized in multiple place.

With your way, it is *very reasonable* for a user to assume that this:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = { 1, 2, 3, 4, 5 };
};

works just as well as this:

struct slk{
slk() {}
slk(int i) : k{ i, 2, 3, 4, 5 } {}
int k[] = { 2, 7 };
};

That's why it's better to just be explicit about the size. That way, you
can never make this mistake.

One more thing: what you are talking about is not a *defect* in the
standard. At *best*, it is an inconsistency. Therefore, what you want is a
*proposal*. This forum is not the place to handle proposal discussions.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-15 20:01:11 UTC
Permalink
No... In your example you're trying to initialize array of size two with 5
literals. That couldn't work.
Post by Nicol Bolas
Post by a***@gmail.com
But now after you've changed example, you are trying to initialize array
of size two with five elements which is incorrect and I would never expect
that.
Guys, are you seriously not seeing anything wrong with the fact that this
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {} //note that I've change those brackets into
braces otherwise the code is incorrect
int k[5] = { 1, 2, 3, 4, 5 };
};
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = { 1, 2, 3, 4, 5 };
};
even though the only difference between those two examples is that in one
size of array is explicitly stated and in the second size of array to be
expected to be deduced by compiler which need I remind you, compiler
already can do it and does it in other scenarios.
Except that those "other scenarios" are very different. Namely, the object
is initialized in *exactly* one place.
In this case, the object is being initialized in multiple place.
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = { 1, 2, 3, 4, 5 };
};
struct slk{
slk() {}
slk(int i) : k{ i, 2, 3, 4, 5 } {}
int k[] = { 2, 7 };
};
That's why it's better to just be explicit about the size. That way, you
can never make this mistake.
One more thing: what you are talking about is not a *defect* in the
standard. At *best*, it is an inconsistency. Therefore, what you want is
a *proposal*. This forum is not the place to handle proposal discussions.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-15 20:50:23 UTC
Permalink
Post by a***@gmail.com
No... In your example you're trying to initialize array of size two with 5
literals. That couldn't work.
Actually, in both examples the array size has undefined size.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-16 10:04:18 UTC
Permalink
Yes but only because standard rules are counter-intuitive in that
particular scenario.
No matter how much I will be discussing it here to me it will always be
unnatural that this can be compiled:

struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[5] = {1, 2, 3, 4, 5};
};

and this won't:
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = {1, 2, 3, 4, 5};
};

It's unnatural, counter-intuitive, illogical and hurtful.
Post by Thiago Macieira
Post by a***@gmail.com
No... In your example you're trying to initialize array of size two with
5
Post by a***@gmail.com
literals. That couldn't work.
Actually, in both examples the array size has undefined size.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-03-16 10:26:45 UTC
Permalink
Post by a***@gmail.com
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = {1, 2, 3, 4, 5};
};
It's unnatural, counter-intuitive, illogical and hurtful.
Um, how big is k supposed to be here? The size is supposed to be deduced from an unused initializer?

Deducing the size of an array from the syntax of the initializer-clause in its init-declarator, regardless of whether that really is the initializer of the object, but many will find that counter-intuitive. The line has to be drawn somewhere.
Post by a***@gmail.com
Daniel, thank you for your input. Agree with what you've said and that is basically on the lines of my thinking. Could you perhaps think of any example in which size of that array would be difficult (for compiler) to deduce from the initializer list that is.
There could be some difficulty in case of brace elision, especially with template type dependency. Unused initializers have to be compiled enough to tell initialization of multiple array elements from initialization of only the first element.

struct x {
int a, b;
};

template< typename t >
struct s {
t m[] = { 1, 2 };
};

s< int > a; // array size 2
s< x > b; // array size 1
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
a***@gmail.com
2015-03-16 16:06:56 UTC
Permalink
Size of k is deduced from the initializer.
Why unused initializer? Surely the array would be initialized from that
initializer so that initializer is used?

In the example you've provided:
a) array size always == 2
b) t must be convertible to type of what initializer list's element type is.
Post by a***@gmail.com
struct slk{
slk() {}
slk(int i) : k{ i, 7 } {}
int k[] = {1, 2, 3, 4, 5};
};
It's unnatural, counter-intuitive, illogical and hurtful.
Um, how big is k supposed to be here? The size is supposed to be deduced
from an unused initializer?
Deducing the size of an array from the syntax of the initializer-clause in
its init-declarator, regardless of whether that really is the initializer
of the object, but many will find that counter-intuitive. The line has to
be drawn somewhere.
Daniel, thank you for your input. Agree with what you've said and that is
basically on the lines of my thinking. Could you perhaps think of any
example in which size of that array would be difficult (for compiler) to
deduce from the initializer list that is.
There could be some difficulty in case of brace elision, especially with
template type dependency. Unused initializers have to be compiled enough to
tell initialization of multiple array elements from initialization of only
the first element.
struct x {
int a, b;
};
template< typename t >
struct s {
t m[] = { 1, 2 };
};
s< int > a; // array size 2
s< x > b; // array size 1
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-16 16:27:22 UTC
Permalink
Post by a***@gmail.com
Size of k is deduced from the initializer.
Why unused initializer? Surely the array would be initialized from that
initializer so that initializer is used?
We are talking about cases when the non-static data member initializer
is not used -
cases where a ctor-initializer overrules it. Such as

struct X
{
vector<int> v = {1,2,3,4};
X() {}
X(initializer_list<int> i) : v(i) /* non-static data member
initializer for v is not used */ {};
};

If you do X x; x.v has four elements. If you do X x{1,2}; x.v has two
elements. The same logic
applies to an initializer for an array. You're suggesting that there
would be an exception to
these rules where an unsized array would always deduce its size from a
non-static data
member initializer, even when that initializer is not used to actually
initialize the array.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Rodríguez Ibeas
2015-03-16 16:29:45 UTC
Permalink
Post by a***@gmail.com
Size of k is deduced from the initializer.
Why unused initializer? Surely the array would be initialized from that
initializer so that initializer is used?
Whether that initializer is used or not depends on whether the initializer
list in the constructor explicitly mentions the member or it doesn't. In
the code you presented:

slk(int i) : k{ i, 7 } {}

The 'k' is explicitly mentioned and thus the initializer in the class
definition is *unused* (if you remove the member initialization from the
constructor, then it would be used). Honestly, the size of the array in
the case of a class is important enough that I believe it should be
explicitly stated --i.e. I am fine with the current rules. To objects of
the same type need to have the same size, having the compiler deduce the
size based on the initialization is fine for a local variable, but this is
not for one object, but a class of objects.
Post by a***@gmail.com
a) array size always == 2
b) t must be convertible to type of what initializer list's element type is.
Post by a***@gmail.com
Why would it? If you wrote that in the stack you would get sizes 2 and 1
for the two cases. I find the inconsistency on the variable vs. member
declaration less problematic than the alternative. Currently you get a
consistent error the syntax is disallowed for class definitions, otherwise
you would get either different behavior or an error that happens some times
but not always.

David
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-16 16:19:52 UTC
Permalink
Post by a***@gmail.com
It's unnatural, counter-intuitive, illogical and hurtful.
I'm not going to argue on unnatural and counter-intuitive. Hurtful is entirely
subjective.

But the current behaviour is entirely logical. You just disagree with the
logic. That's different.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
ajay kumar
2015-10-04 11:16:30 UTC
Permalink
http://comsciguide.blogspot.com/2015/01/enum-make-u-r-names-as-data-types.html
Post by a***@gmail.com
Guys,
Taken from stackoverflow, but actually I came up against identical problem
int k[] ={1,2,3,4,5};
struct slk{
int k[] ={1,2,3,4,5};};
First compiles, second doesn't saying that there is too many initializers.
Surely when looking at it soberly those two lines of code are identical and
one being in a global namespace and second being in a namespace of struct
shouldn't have any impact on compiler behavior. Why is it that in First
example compiler can deduce the size and in second it either cannot or
won't do it? AFAIC, First notion is more preferable from the point of view
of being easier modifiable, avoiding silly mistakes when providing explicit
size of array, heck, even Bjarne in either one of his books of papers
enum a { one = 1, two, three};
enum a {one = 1, two = 2, three = 3};
Why is second option not allowed?!? It goes against every logical instinct.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Johannes Schaub' via ISO C++ Standard - Discussion
2015-10-04 12:10:15 UTC
Permalink
Not sure whether you are aware of the workaround, but you can get the
correct type using `decltype`

template<typename T>
using id = T;

#define inclass_array(T, N, ...) decltype(id< T > __VA_ARGS__) N =
__VA_ARGS__

struct slk
{
inclass_array(int[], k, {1,2,3,4,5});
};
Post by a***@gmail.com
Guys,
Taken from stackoverflow, but actually I came up against identical problem
int k[] ={1,2,3,4,5};
struct slk
{
int k[] ={1,2,3,4,5};
};
First compiles, second doesn't saying that there is too many initializers.
Surely when looking at it soberly those two lines of code are identical and
one being in a global namespace and second being in a namespace of struct
shouldn't have any impact on compiler behavior. Why is it that in First
example compiler can deduce the size and in second it either cannot or won't
do it? AFAIC, First notion is more preferable from the point of view of
being easier modifiable, avoiding silly mistakes when providing explicit
size of array, heck, even Bjarne in either one of his books of papers
enum a { one = 1, two, three};
enum a {one = 1, two = 2, three = 3};
Why is second option not allowed?!? It goes against every logical instinct.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Johannes Schaub' via ISO C++ Standard - Discussion
2015-10-04 12:15:55 UTC
Permalink
GCC 5.2 categorizes the type as a reference (huh?.. clang doesn't do
that...), you can easily get around this by applying
remove_reference..

typename std::remove_reference_t<decltype(id< T > __VA_ARGS__)>
Post by 'Johannes Schaub' via ISO C++ Standard - Discussion
Not sure whether you are aware of the workaround, but you can get the
correct type using `decltype`
template<typename T>
using id = T;
#define inclass_array(T, N, ...) decltype(id< T > __VA_ARGS__) N =
__VA_ARGS__
struct slk
{
inclass_array(int[], k, {1,2,3,4,5});
};
Post by a***@gmail.com
Guys,
Taken from stackoverflow, but actually I came up against identical problem
int k[] ={1,2,3,4,5};
struct slk
{
int k[] ={1,2,3,4,5};
};
First compiles, second doesn't saying that there is too many initializers.
Surely when looking at it soberly those two lines of code are identical and
one being in a global namespace and second being in a namespace of struct
shouldn't have any impact on compiler behavior. Why is it that in First
example compiler can deduce the size and in second it either cannot or won't
do it? AFAIC, First notion is more preferable from the point of view of
being easier modifiable, avoiding silly mistakes when providing explicit
size of array, heck, even Bjarne in either one of his books of papers
enum a { one = 1, two, three};
enum a {one = 1, two = 2, three = 3};
Why is second option not allowed?!? It goes against every logical instinct.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Continue reading on narkive:
Loading...