Brace elision in std::array
I'm compiling using g++
for C++ 17. I have the following:
std::array<std::vector<int>, 2> v = {{ {1,2}, {3,4} }};
I don't understand why if I remove the double braces for the array it does not work anymore.
std::array<std::vector<int>, 2> v = { {1,2}, {3,4} }; // Does not compile
I understand how std::array
works and the need for the double braces in general, but as I'm compiling for C++17 I expected brace elision to come into play.
Why is brace elision not applicable here?
c++ c++17 list-initialization
|
show 1 more comment
I'm compiling using g++
for C++ 17. I have the following:
std::array<std::vector<int>, 2> v = {{ {1,2}, {3,4} }};
I don't understand why if I remove the double braces for the array it does not work anymore.
std::array<std::vector<int>, 2> v = { {1,2}, {3,4} }; // Does not compile
I understand how std::array
works and the need for the double braces in general, but as I'm compiling for C++17 I expected brace elision to come into play.
Why is brace elision not applicable here?
c++ c++17 list-initialization
1
What do you mean by "not working" - the code compiles with GCC 8.1.0 and-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:36
1
@NeilButterworth He meant about this. If I understood correctly.
– JeJo
Nov 14 '18 at 17:39
@JeJo Yes you are correct.
– Svalorzen
Nov 14 '18 at 17:40
@JeJo That code isn't compiled with-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:41
@NeilButterworthg++ -std=c++17 main.cpp main.cpp: In function ‘int main()’: main.cpp:5:56: error: too many initializers for ‘std::array<std::vector<int>, 2>’ std::array<std::vector<int>, 2> v = { {1,2}, {3,4} };
– Svalorzen
Nov 14 '18 at 17:43
|
show 1 more comment
I'm compiling using g++
for C++ 17. I have the following:
std::array<std::vector<int>, 2> v = {{ {1,2}, {3,4} }};
I don't understand why if I remove the double braces for the array it does not work anymore.
std::array<std::vector<int>, 2> v = { {1,2}, {3,4} }; // Does not compile
I understand how std::array
works and the need for the double braces in general, but as I'm compiling for C++17 I expected brace elision to come into play.
Why is brace elision not applicable here?
c++ c++17 list-initialization
I'm compiling using g++
for C++ 17. I have the following:
std::array<std::vector<int>, 2> v = {{ {1,2}, {3,4} }};
I don't understand why if I remove the double braces for the array it does not work anymore.
std::array<std::vector<int>, 2> v = { {1,2}, {3,4} }; // Does not compile
I understand how std::array
works and the need for the double braces in general, but as I'm compiling for C++17 I expected brace elision to come into play.
Why is brace elision not applicable here?
c++ c++17 list-initialization
c++ c++17 list-initialization
edited Nov 14 '18 at 17:41
Svalorzen
asked Nov 14 '18 at 17:32
SvalorzenSvalorzen
3,30521746
3,30521746
1
What do you mean by "not working" - the code compiles with GCC 8.1.0 and-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:36
1
@NeilButterworth He meant about this. If I understood correctly.
– JeJo
Nov 14 '18 at 17:39
@JeJo Yes you are correct.
– Svalorzen
Nov 14 '18 at 17:40
@JeJo That code isn't compiled with-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:41
@NeilButterworthg++ -std=c++17 main.cpp main.cpp: In function ‘int main()’: main.cpp:5:56: error: too many initializers for ‘std::array<std::vector<int>, 2>’ std::array<std::vector<int>, 2> v = { {1,2}, {3,4} };
– Svalorzen
Nov 14 '18 at 17:43
|
show 1 more comment
1
What do you mean by "not working" - the code compiles with GCC 8.1.0 and-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:36
1
@NeilButterworth He meant about this. If I understood correctly.
– JeJo
Nov 14 '18 at 17:39
@JeJo Yes you are correct.
– Svalorzen
Nov 14 '18 at 17:40
@JeJo That code isn't compiled with-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:41
@NeilButterworthg++ -std=c++17 main.cpp main.cpp: In function ‘int main()’: main.cpp:5:56: error: too many initializers for ‘std::array<std::vector<int>, 2>’ std::array<std::vector<int>, 2> v = { {1,2}, {3,4} };
– Svalorzen
Nov 14 '18 at 17:43
1
1
What do you mean by "not working" - the code compiles with GCC 8.1.0 and
-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:36
What do you mean by "not working" - the code compiles with GCC 8.1.0 and
-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:36
1
1
@NeilButterworth He meant about this. If I understood correctly.
– JeJo
Nov 14 '18 at 17:39
@NeilButterworth He meant about this. If I understood correctly.
– JeJo
Nov 14 '18 at 17:39
@JeJo Yes you are correct.
– Svalorzen
Nov 14 '18 at 17:40
@JeJo Yes you are correct.
– Svalorzen
Nov 14 '18 at 17:40
@JeJo That code isn't compiled with
-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:41
@JeJo That code isn't compiled with
-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:41
@NeilButterworth
g++ -std=c++17 main.cpp main.cpp: In function ‘int main()’: main.cpp:5:56: error: too many initializers for ‘std::array<std::vector<int>, 2>’ std::array<std::vector<int>, 2> v = { {1,2}, {3,4} };
– Svalorzen
Nov 14 '18 at 17:43
@NeilButterworth
g++ -std=c++17 main.cpp main.cpp: In function ‘int main()’: main.cpp:5:56: error: too many initializers for ‘std::array<std::vector<int>, 2>’ std::array<std::vector<int>, 2> v = { {1,2}, {3,4} };
– Svalorzen
Nov 14 '18 at 17:43
|
show 1 more comment
2 Answers
2
active
oldest
votes
std::array<std::vector<int>, 2>
is effectively
struct array {
std::vector<int> elems[2];
};
elems
is a subaggregate just fine. The issue is that per the language rules, if the initializer starts with a {
it's always assumed that you aren't eliding braces; instead, {1, 2}
is taken as the initializer of the entire subaggregate elems
, attempting to initialize its first element with 1
and second element with 2
(this is obviously invalid - you can't convert an integer to a vector
- but doesn't affect the interpretation), and {3, 4}
is considered the initializer for the thing after elems
- and since there are no such thing, it's another error.
Initializing the first element with something that's not a braced-init-list is sufficient to trigger brace elision:
std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} };
Note that from a specification perspective, the library doesn't guarantee initialization of std::array<T, N>
from anything other than another std::array<T, N>
or a list of "up to N elements whose types are convertible to T
". This notably excludes braced-init-lists because they have no type, and actually also disallows "double braces" because that's just a special case of having a single element that is a braced-init-list .
This is an area where we may have been better off specifying it with code. The core language rules defy easy specification in words and the implementation details will leak out - and have already done so.
Thank you for the clarification, it was very useful. I'm not sure I fully understood your second remark though. The initialization is not guaranteed in other cases means that it is unspecified behaviour? Why are also double braces disallowed (considering that the brace elision rule was made pretty much forstd::array
IIUC)?
– Svalorzen
Nov 14 '18 at 20:49
2
Formally, it's undefined behavior: the standard defines no behavior when astd::array
is initialized with anything else. Double braces are not in the "defined to work" case because they are actually an initializer list containing a single element (the inner braced-init-list) with no type. Brace elision goes all the way back to C.std::array
has nothing to do with it. The formal UB here is certainly a defect; the problem is finding the right words to define the behavior, preferably without regurgitating the several pages of aggregate initialization rules.
– T.C.
Nov 14 '18 at 23:52
add a comment |
As T.C. pointed out my original interpretation was not corret, brace elision is allowed see [dcl.init.aggr]p15:
Braces can be elided in an initializer-list as follows. If the
initializer-list begins with a left brace, then the succeeding
comma-separated list of initializer-clauses initializes the elements
of a subaggregate; it is erroneous for there to be more
initializer-clauses than elements. If, however, the initializer-list
for a subaggregate does not begin with a left brace, then only enough
initializer-clauses from the list are taken to initialize the elements
of the subaggregate; any remaining initializer-clauses are left to
initialize the next element of the aggregate of which the current
subaggregate is an element. ...
but std::array
according to array.overview:
An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.
which is not the case we have.
But in my example the double brace is only required forstd::array
, which is an an aggregate, right? Or is brace elision only allowed when it's aggregate all the way down?
– Svalorzen
Nov 14 '18 at 17:55
I just noticed thatstd::array<std::vector<int>, 2> v = {std::vector<int>{1,2}, std::vector<int>{3,4}};
compiles. Is this also the "does not begin with a left brace" case?
– Svalorzen
Nov 14 '18 at 18:01
1
@Svalorzen that is a different case of explicit initialization covered by dcl.init.aggrp3.2 and dcl.init.aggrp4.2)
– Shafik Yaghmour
Nov 14 '18 at 18:25
OP's example is attempting to elide the braces for thestd::vector<int>[2]
subaggregate.
– T.C.
Nov 14 '18 at 20:05
@T.C. so are you saying it should work and the compilers are non-conforming or that my choice of words is not correct or that it should not work but I am quoting the wrong parts?
– Shafik Yaghmour
Nov 14 '18 at 20:09
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53305831%2fbrace-elision-in-stdarraystdvector%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
std::array<std::vector<int>, 2>
is effectively
struct array {
std::vector<int> elems[2];
};
elems
is a subaggregate just fine. The issue is that per the language rules, if the initializer starts with a {
it's always assumed that you aren't eliding braces; instead, {1, 2}
is taken as the initializer of the entire subaggregate elems
, attempting to initialize its first element with 1
and second element with 2
(this is obviously invalid - you can't convert an integer to a vector
- but doesn't affect the interpretation), and {3, 4}
is considered the initializer for the thing after elems
- and since there are no such thing, it's another error.
Initializing the first element with something that's not a braced-init-list is sufficient to trigger brace elision:
std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} };
Note that from a specification perspective, the library doesn't guarantee initialization of std::array<T, N>
from anything other than another std::array<T, N>
or a list of "up to N elements whose types are convertible to T
". This notably excludes braced-init-lists because they have no type, and actually also disallows "double braces" because that's just a special case of having a single element that is a braced-init-list .
This is an area where we may have been better off specifying it with code. The core language rules defy easy specification in words and the implementation details will leak out - and have already done so.
Thank you for the clarification, it was very useful. I'm not sure I fully understood your second remark though. The initialization is not guaranteed in other cases means that it is unspecified behaviour? Why are also double braces disallowed (considering that the brace elision rule was made pretty much forstd::array
IIUC)?
– Svalorzen
Nov 14 '18 at 20:49
2
Formally, it's undefined behavior: the standard defines no behavior when astd::array
is initialized with anything else. Double braces are not in the "defined to work" case because they are actually an initializer list containing a single element (the inner braced-init-list) with no type. Brace elision goes all the way back to C.std::array
has nothing to do with it. The formal UB here is certainly a defect; the problem is finding the right words to define the behavior, preferably without regurgitating the several pages of aggregate initialization rules.
– T.C.
Nov 14 '18 at 23:52
add a comment |
std::array<std::vector<int>, 2>
is effectively
struct array {
std::vector<int> elems[2];
};
elems
is a subaggregate just fine. The issue is that per the language rules, if the initializer starts with a {
it's always assumed that you aren't eliding braces; instead, {1, 2}
is taken as the initializer of the entire subaggregate elems
, attempting to initialize its first element with 1
and second element with 2
(this is obviously invalid - you can't convert an integer to a vector
- but doesn't affect the interpretation), and {3, 4}
is considered the initializer for the thing after elems
- and since there are no such thing, it's another error.
Initializing the first element with something that's not a braced-init-list is sufficient to trigger brace elision:
std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} };
Note that from a specification perspective, the library doesn't guarantee initialization of std::array<T, N>
from anything other than another std::array<T, N>
or a list of "up to N elements whose types are convertible to T
". This notably excludes braced-init-lists because they have no type, and actually also disallows "double braces" because that's just a special case of having a single element that is a braced-init-list .
This is an area where we may have been better off specifying it with code. The core language rules defy easy specification in words and the implementation details will leak out - and have already done so.
Thank you for the clarification, it was very useful. I'm not sure I fully understood your second remark though. The initialization is not guaranteed in other cases means that it is unspecified behaviour? Why are also double braces disallowed (considering that the brace elision rule was made pretty much forstd::array
IIUC)?
– Svalorzen
Nov 14 '18 at 20:49
2
Formally, it's undefined behavior: the standard defines no behavior when astd::array
is initialized with anything else. Double braces are not in the "defined to work" case because they are actually an initializer list containing a single element (the inner braced-init-list) with no type. Brace elision goes all the way back to C.std::array
has nothing to do with it. The formal UB here is certainly a defect; the problem is finding the right words to define the behavior, preferably without regurgitating the several pages of aggregate initialization rules.
– T.C.
Nov 14 '18 at 23:52
add a comment |
std::array<std::vector<int>, 2>
is effectively
struct array {
std::vector<int> elems[2];
};
elems
is a subaggregate just fine. The issue is that per the language rules, if the initializer starts with a {
it's always assumed that you aren't eliding braces; instead, {1, 2}
is taken as the initializer of the entire subaggregate elems
, attempting to initialize its first element with 1
and second element with 2
(this is obviously invalid - you can't convert an integer to a vector
- but doesn't affect the interpretation), and {3, 4}
is considered the initializer for the thing after elems
- and since there are no such thing, it's another error.
Initializing the first element with something that's not a braced-init-list is sufficient to trigger brace elision:
std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} };
Note that from a specification perspective, the library doesn't guarantee initialization of std::array<T, N>
from anything other than another std::array<T, N>
or a list of "up to N elements whose types are convertible to T
". This notably excludes braced-init-lists because they have no type, and actually also disallows "double braces" because that's just a special case of having a single element that is a braced-init-list .
This is an area where we may have been better off specifying it with code. The core language rules defy easy specification in words and the implementation details will leak out - and have already done so.
std::array<std::vector<int>, 2>
is effectively
struct array {
std::vector<int> elems[2];
};
elems
is a subaggregate just fine. The issue is that per the language rules, if the initializer starts with a {
it's always assumed that you aren't eliding braces; instead, {1, 2}
is taken as the initializer of the entire subaggregate elems
, attempting to initialize its first element with 1
and second element with 2
(this is obviously invalid - you can't convert an integer to a vector
- but doesn't affect the interpretation), and {3, 4}
is considered the initializer for the thing after elems
- and since there are no such thing, it's another error.
Initializing the first element with something that's not a braced-init-list is sufficient to trigger brace elision:
std::array<std::vector<int>, 2> v = { std::vector<int>{1,2}, {3,4} };
Note that from a specification perspective, the library doesn't guarantee initialization of std::array<T, N>
from anything other than another std::array<T, N>
or a list of "up to N elements whose types are convertible to T
". This notably excludes braced-init-lists because they have no type, and actually also disallows "double braces" because that's just a special case of having a single element that is a braced-init-list .
This is an area where we may have been better off specifying it with code. The core language rules defy easy specification in words and the implementation details will leak out - and have already done so.
edited Nov 14 '18 at 23:54
answered Nov 14 '18 at 20:19
T.C.T.C.
107k14219323
107k14219323
Thank you for the clarification, it was very useful. I'm not sure I fully understood your second remark though. The initialization is not guaranteed in other cases means that it is unspecified behaviour? Why are also double braces disallowed (considering that the brace elision rule was made pretty much forstd::array
IIUC)?
– Svalorzen
Nov 14 '18 at 20:49
2
Formally, it's undefined behavior: the standard defines no behavior when astd::array
is initialized with anything else. Double braces are not in the "defined to work" case because they are actually an initializer list containing a single element (the inner braced-init-list) with no type. Brace elision goes all the way back to C.std::array
has nothing to do with it. The formal UB here is certainly a defect; the problem is finding the right words to define the behavior, preferably without regurgitating the several pages of aggregate initialization rules.
– T.C.
Nov 14 '18 at 23:52
add a comment |
Thank you for the clarification, it was very useful. I'm not sure I fully understood your second remark though. The initialization is not guaranteed in other cases means that it is unspecified behaviour? Why are also double braces disallowed (considering that the brace elision rule was made pretty much forstd::array
IIUC)?
– Svalorzen
Nov 14 '18 at 20:49
2
Formally, it's undefined behavior: the standard defines no behavior when astd::array
is initialized with anything else. Double braces are not in the "defined to work" case because they are actually an initializer list containing a single element (the inner braced-init-list) with no type. Brace elision goes all the way back to C.std::array
has nothing to do with it. The formal UB here is certainly a defect; the problem is finding the right words to define the behavior, preferably without regurgitating the several pages of aggregate initialization rules.
– T.C.
Nov 14 '18 at 23:52
Thank you for the clarification, it was very useful. I'm not sure I fully understood your second remark though. The initialization is not guaranteed in other cases means that it is unspecified behaviour? Why are also double braces disallowed (considering that the brace elision rule was made pretty much for
std::array
IIUC)?– Svalorzen
Nov 14 '18 at 20:49
Thank you for the clarification, it was very useful. I'm not sure I fully understood your second remark though. The initialization is not guaranteed in other cases means that it is unspecified behaviour? Why are also double braces disallowed (considering that the brace elision rule was made pretty much for
std::array
IIUC)?– Svalorzen
Nov 14 '18 at 20:49
2
2
Formally, it's undefined behavior: the standard defines no behavior when a
std::array
is initialized with anything else. Double braces are not in the "defined to work" case because they are actually an initializer list containing a single element (the inner braced-init-list) with no type. Brace elision goes all the way back to C. std::array
has nothing to do with it. The formal UB here is certainly a defect; the problem is finding the right words to define the behavior, preferably without regurgitating the several pages of aggregate initialization rules.– T.C.
Nov 14 '18 at 23:52
Formally, it's undefined behavior: the standard defines no behavior when a
std::array
is initialized with anything else. Double braces are not in the "defined to work" case because they are actually an initializer list containing a single element (the inner braced-init-list) with no type. Brace elision goes all the way back to C. std::array
has nothing to do with it. The formal UB here is certainly a defect; the problem is finding the right words to define the behavior, preferably without regurgitating the several pages of aggregate initialization rules.– T.C.
Nov 14 '18 at 23:52
add a comment |
As T.C. pointed out my original interpretation was not corret, brace elision is allowed see [dcl.init.aggr]p15:
Braces can be elided in an initializer-list as follows. If the
initializer-list begins with a left brace, then the succeeding
comma-separated list of initializer-clauses initializes the elements
of a subaggregate; it is erroneous for there to be more
initializer-clauses than elements. If, however, the initializer-list
for a subaggregate does not begin with a left brace, then only enough
initializer-clauses from the list are taken to initialize the elements
of the subaggregate; any remaining initializer-clauses are left to
initialize the next element of the aggregate of which the current
subaggregate is an element. ...
but std::array
according to array.overview:
An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.
which is not the case we have.
But in my example the double brace is only required forstd::array
, which is an an aggregate, right? Or is brace elision only allowed when it's aggregate all the way down?
– Svalorzen
Nov 14 '18 at 17:55
I just noticed thatstd::array<std::vector<int>, 2> v = {std::vector<int>{1,2}, std::vector<int>{3,4}};
compiles. Is this also the "does not begin with a left brace" case?
– Svalorzen
Nov 14 '18 at 18:01
1
@Svalorzen that is a different case of explicit initialization covered by dcl.init.aggrp3.2 and dcl.init.aggrp4.2)
– Shafik Yaghmour
Nov 14 '18 at 18:25
OP's example is attempting to elide the braces for thestd::vector<int>[2]
subaggregate.
– T.C.
Nov 14 '18 at 20:05
@T.C. so are you saying it should work and the compilers are non-conforming or that my choice of words is not correct or that it should not work but I am quoting the wrong parts?
– Shafik Yaghmour
Nov 14 '18 at 20:09
|
show 2 more comments
As T.C. pointed out my original interpretation was not corret, brace elision is allowed see [dcl.init.aggr]p15:
Braces can be elided in an initializer-list as follows. If the
initializer-list begins with a left brace, then the succeeding
comma-separated list of initializer-clauses initializes the elements
of a subaggregate; it is erroneous for there to be more
initializer-clauses than elements. If, however, the initializer-list
for a subaggregate does not begin with a left brace, then only enough
initializer-clauses from the list are taken to initialize the elements
of the subaggregate; any remaining initializer-clauses are left to
initialize the next element of the aggregate of which the current
subaggregate is an element. ...
but std::array
according to array.overview:
An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.
which is not the case we have.
But in my example the double brace is only required forstd::array
, which is an an aggregate, right? Or is brace elision only allowed when it's aggregate all the way down?
– Svalorzen
Nov 14 '18 at 17:55
I just noticed thatstd::array<std::vector<int>, 2> v = {std::vector<int>{1,2}, std::vector<int>{3,4}};
compiles. Is this also the "does not begin with a left brace" case?
– Svalorzen
Nov 14 '18 at 18:01
1
@Svalorzen that is a different case of explicit initialization covered by dcl.init.aggrp3.2 and dcl.init.aggrp4.2)
– Shafik Yaghmour
Nov 14 '18 at 18:25
OP's example is attempting to elide the braces for thestd::vector<int>[2]
subaggregate.
– T.C.
Nov 14 '18 at 20:05
@T.C. so are you saying it should work and the compilers are non-conforming or that my choice of words is not correct or that it should not work but I am quoting the wrong parts?
– Shafik Yaghmour
Nov 14 '18 at 20:09
|
show 2 more comments
As T.C. pointed out my original interpretation was not corret, brace elision is allowed see [dcl.init.aggr]p15:
Braces can be elided in an initializer-list as follows. If the
initializer-list begins with a left brace, then the succeeding
comma-separated list of initializer-clauses initializes the elements
of a subaggregate; it is erroneous for there to be more
initializer-clauses than elements. If, however, the initializer-list
for a subaggregate does not begin with a left brace, then only enough
initializer-clauses from the list are taken to initialize the elements
of the subaggregate; any remaining initializer-clauses are left to
initialize the next element of the aggregate of which the current
subaggregate is an element. ...
but std::array
according to array.overview:
An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.
which is not the case we have.
As T.C. pointed out my original interpretation was not corret, brace elision is allowed see [dcl.init.aggr]p15:
Braces can be elided in an initializer-list as follows. If the
initializer-list begins with a left brace, then the succeeding
comma-separated list of initializer-clauses initializes the elements
of a subaggregate; it is erroneous for there to be more
initializer-clauses than elements. If, however, the initializer-list
for a subaggregate does not begin with a left brace, then only enough
initializer-clauses from the list are taken to initialize the elements
of the subaggregate; any remaining initializer-clauses are left to
initialize the next element of the aggregate of which the current
subaggregate is an element. ...
but std::array
according to array.overview:
An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.
which is not the case we have.
edited Nov 14 '18 at 21:35
answered Nov 14 '18 at 17:52
Shafik YaghmourShafik Yaghmour
126k23326539
126k23326539
But in my example the double brace is only required forstd::array
, which is an an aggregate, right? Or is brace elision only allowed when it's aggregate all the way down?
– Svalorzen
Nov 14 '18 at 17:55
I just noticed thatstd::array<std::vector<int>, 2> v = {std::vector<int>{1,2}, std::vector<int>{3,4}};
compiles. Is this also the "does not begin with a left brace" case?
– Svalorzen
Nov 14 '18 at 18:01
1
@Svalorzen that is a different case of explicit initialization covered by dcl.init.aggrp3.2 and dcl.init.aggrp4.2)
– Shafik Yaghmour
Nov 14 '18 at 18:25
OP's example is attempting to elide the braces for thestd::vector<int>[2]
subaggregate.
– T.C.
Nov 14 '18 at 20:05
@T.C. so are you saying it should work and the compilers are non-conforming or that my choice of words is not correct or that it should not work but I am quoting the wrong parts?
– Shafik Yaghmour
Nov 14 '18 at 20:09
|
show 2 more comments
But in my example the double brace is only required forstd::array
, which is an an aggregate, right? Or is brace elision only allowed when it's aggregate all the way down?
– Svalorzen
Nov 14 '18 at 17:55
I just noticed thatstd::array<std::vector<int>, 2> v = {std::vector<int>{1,2}, std::vector<int>{3,4}};
compiles. Is this also the "does not begin with a left brace" case?
– Svalorzen
Nov 14 '18 at 18:01
1
@Svalorzen that is a different case of explicit initialization covered by dcl.init.aggrp3.2 and dcl.init.aggrp4.2)
– Shafik Yaghmour
Nov 14 '18 at 18:25
OP's example is attempting to elide the braces for thestd::vector<int>[2]
subaggregate.
– T.C.
Nov 14 '18 at 20:05
@T.C. so are you saying it should work and the compilers are non-conforming or that my choice of words is not correct or that it should not work but I am quoting the wrong parts?
– Shafik Yaghmour
Nov 14 '18 at 20:09
But in my example the double brace is only required for
std::array
, which is an an aggregate, right? Or is brace elision only allowed when it's aggregate all the way down?– Svalorzen
Nov 14 '18 at 17:55
But in my example the double brace is only required for
std::array
, which is an an aggregate, right? Or is brace elision only allowed when it's aggregate all the way down?– Svalorzen
Nov 14 '18 at 17:55
I just noticed that
std::array<std::vector<int>, 2> v = {std::vector<int>{1,2}, std::vector<int>{3,4}};
compiles. Is this also the "does not begin with a left brace" case?– Svalorzen
Nov 14 '18 at 18:01
I just noticed that
std::array<std::vector<int>, 2> v = {std::vector<int>{1,2}, std::vector<int>{3,4}};
compiles. Is this also the "does not begin with a left brace" case?– Svalorzen
Nov 14 '18 at 18:01
1
1
@Svalorzen that is a different case of explicit initialization covered by dcl.init.aggrp3.2 and dcl.init.aggrp4.2)
– Shafik Yaghmour
Nov 14 '18 at 18:25
@Svalorzen that is a different case of explicit initialization covered by dcl.init.aggrp3.2 and dcl.init.aggrp4.2)
– Shafik Yaghmour
Nov 14 '18 at 18:25
OP's example is attempting to elide the braces for the
std::vector<int>[2]
subaggregate.– T.C.
Nov 14 '18 at 20:05
OP's example is attempting to elide the braces for the
std::vector<int>[2]
subaggregate.– T.C.
Nov 14 '18 at 20:05
@T.C. so are you saying it should work and the compilers are non-conforming or that my choice of words is not correct or that it should not work but I am quoting the wrong parts?
– Shafik Yaghmour
Nov 14 '18 at 20:09
@T.C. so are you saying it should work and the compilers are non-conforming or that my choice of words is not correct or that it should not work but I am quoting the wrong parts?
– Shafik Yaghmour
Nov 14 '18 at 20:09
|
show 2 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53305831%2fbrace-elision-in-stdarraystdvector%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
What do you mean by "not working" - the code compiles with GCC 8.1.0 and
-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:36
1
@NeilButterworth He meant about this. If I understood correctly.
– JeJo
Nov 14 '18 at 17:39
@JeJo Yes you are correct.
– Svalorzen
Nov 14 '18 at 17:40
@JeJo That code isn't compiled with
-std=c++17
– Neil Butterworth
Nov 14 '18 at 17:41
@NeilButterworth
g++ -std=c++17 main.cpp main.cpp: In function ‘int main()’: main.cpp:5:56: error: too many initializers for ‘std::array<std::vector<int>, 2>’ std::array<std::vector<int>, 2> v = { {1,2}, {3,4} };
– Svalorzen
Nov 14 '18 at 17:43