Shall structured binding to a copy of a const c-array be const?
Consider this code (demo):
#include <tuple>
#include <type_traits>
struct Ag{int i;int j;};
using T = std::tuple<int,int>;
using Ar = int[2];
const Ag ag {};
const T t {};
const Ar ar {};
void bind_ag(){
auto [i,j] = ag;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_t(){
auto [i,j] = t;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_ar(){
auto [i,j] = ar;
static_assert(std::is_same_v<decltype((i)),int&>); //For GCC
static_assert(std::is_same_v<decltype((i)),const int&>); //For Clang (and standard?)
}
A structured binding to a copy of a const
c-array are declared const by Clang and non-const by GCC.
The behavior of GCC for c-array is consistent with the behavior observed for aggregate or tuple-like types.
On the other hand from my reading of the standard, I suppose Clang follows what is written. In [dcl.struct.bind]/1 e has type cv A where A is the type of the initializer expression and the cv is the cv-qualifier of the structured binding declaration. And the type of the initializer expression ar
is accordingly to [expr.type]/1 const int[2]
.
What should be expected? My opinion is that Clang follows the standard. On the other hand I feel the intent was that the behaviors for array, aggregate and tuple-like types were equivalent.
c++ language-lawyer c++17 structured-bindings
add a comment |
Consider this code (demo):
#include <tuple>
#include <type_traits>
struct Ag{int i;int j;};
using T = std::tuple<int,int>;
using Ar = int[2];
const Ag ag {};
const T t {};
const Ar ar {};
void bind_ag(){
auto [i,j] = ag;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_t(){
auto [i,j] = t;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_ar(){
auto [i,j] = ar;
static_assert(std::is_same_v<decltype((i)),int&>); //For GCC
static_assert(std::is_same_v<decltype((i)),const int&>); //For Clang (and standard?)
}
A structured binding to a copy of a const
c-array are declared const by Clang and non-const by GCC.
The behavior of GCC for c-array is consistent with the behavior observed for aggregate or tuple-like types.
On the other hand from my reading of the standard, I suppose Clang follows what is written. In [dcl.struct.bind]/1 e has type cv A where A is the type of the initializer expression and the cv is the cv-qualifier of the structured binding declaration. And the type of the initializer expression ar
is accordingly to [expr.type]/1 const int[2]
.
What should be expected? My opinion is that Clang follows the standard. On the other hand I feel the intent was that the behaviors for array, aggregate and tuple-like types were equivalent.
c++ language-lawyer c++17 structured-bindings
1
Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 '18 at 14:44
3
gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 '18 at 14:59
add a comment |
Consider this code (demo):
#include <tuple>
#include <type_traits>
struct Ag{int i;int j;};
using T = std::tuple<int,int>;
using Ar = int[2];
const Ag ag {};
const T t {};
const Ar ar {};
void bind_ag(){
auto [i,j] = ag;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_t(){
auto [i,j] = t;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_ar(){
auto [i,j] = ar;
static_assert(std::is_same_v<decltype((i)),int&>); //For GCC
static_assert(std::is_same_v<decltype((i)),const int&>); //For Clang (and standard?)
}
A structured binding to a copy of a const
c-array are declared const by Clang and non-const by GCC.
The behavior of GCC for c-array is consistent with the behavior observed for aggregate or tuple-like types.
On the other hand from my reading of the standard, I suppose Clang follows what is written. In [dcl.struct.bind]/1 e has type cv A where A is the type of the initializer expression and the cv is the cv-qualifier of the structured binding declaration. And the type of the initializer expression ar
is accordingly to [expr.type]/1 const int[2]
.
What should be expected? My opinion is that Clang follows the standard. On the other hand I feel the intent was that the behaviors for array, aggregate and tuple-like types were equivalent.
c++ language-lawyer c++17 structured-bindings
Consider this code (demo):
#include <tuple>
#include <type_traits>
struct Ag{int i;int j;};
using T = std::tuple<int,int>;
using Ar = int[2];
const Ag ag {};
const T t {};
const Ar ar {};
void bind_ag(){
auto [i,j] = ag;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_t(){
auto [i,j] = t;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_ar(){
auto [i,j] = ar;
static_assert(std::is_same_v<decltype((i)),int&>); //For GCC
static_assert(std::is_same_v<decltype((i)),const int&>); //For Clang (and standard?)
}
A structured binding to a copy of a const
c-array are declared const by Clang and non-const by GCC.
The behavior of GCC for c-array is consistent with the behavior observed for aggregate or tuple-like types.
On the other hand from my reading of the standard, I suppose Clang follows what is written. In [dcl.struct.bind]/1 e has type cv A where A is the type of the initializer expression and the cv is the cv-qualifier of the structured binding declaration. And the type of the initializer expression ar
is accordingly to [expr.type]/1 const int[2]
.
What should be expected? My opinion is that Clang follows the standard. On the other hand I feel the intent was that the behaviors for array, aggregate and tuple-like types were equivalent.
c++ language-lawyer c++17 structured-bindings
c++ language-lawyer c++17 structured-bindings
edited Dec 11 '18 at 14:27
Oliv
asked Dec 11 '18 at 14:21
OlivOliv
8,4291956
8,4291956
1
Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 '18 at 14:44
3
gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 '18 at 14:59
add a comment |
1
Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 '18 at 14:44
3
gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 '18 at 14:59
1
1
Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 '18 at 14:44
Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 '18 at 14:44
3
3
gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 '18 at 14:59
gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 '18 at 14:59
add a comment |
1 Answer
1
active
oldest
votes
The wording of the standard in [dcl.struct.bind] says:
If the assignment-expression in the initializer has array type
A
and no ref-qualifier is present,e
has type cvA
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
We have auto [i,j] = ar;
, ar
has array type const int[2]
, and the wording of the standard makes it clear that e
has type const int[2]
. Thus, per the wording, each binding references the element type - which is const int
. Clang is technically correct.
However, as Richard Smith points out in gcc bug 80649:
I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
That seems right. When you write auto x = y;
you'd certainly expect x
to not be top-level const
, but here we have a situation where it still is. I don't think there's a Core issue open for this yet, but there should be.
The cv-qualification cv comes from the decl-specifier-seq ("auto
") not the initialiser ("ar
"), no? Unless it's saying that the qualifiers onA
are merged into cv. But I don't follow why that would be the case; without a ref-qualifier, why would it want to maintain constness? It doesn't do that anywhere else.
– Lightness Races in Orbit
Dec 11 '18 at 16:21
5
@LightnessRacesinOrbit It does - butA
is an array of const, socv A
is still an array of const. I don't think we want to maintain constness, hence Core issue.
– Barry
Dec 11 '18 at 16:25
Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 '18 at 16:56
add a comment |
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%2f53726135%2fshall-structured-binding-to-a-copy-of-a-const-c-array-be-const%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The wording of the standard in [dcl.struct.bind] says:
If the assignment-expression in the initializer has array type
A
and no ref-qualifier is present,e
has type cvA
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
We have auto [i,j] = ar;
, ar
has array type const int[2]
, and the wording of the standard makes it clear that e
has type const int[2]
. Thus, per the wording, each binding references the element type - which is const int
. Clang is technically correct.
However, as Richard Smith points out in gcc bug 80649:
I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
That seems right. When you write auto x = y;
you'd certainly expect x
to not be top-level const
, but here we have a situation where it still is. I don't think there's a Core issue open for this yet, but there should be.
The cv-qualification cv comes from the decl-specifier-seq ("auto
") not the initialiser ("ar
"), no? Unless it's saying that the qualifiers onA
are merged into cv. But I don't follow why that would be the case; without a ref-qualifier, why would it want to maintain constness? It doesn't do that anywhere else.
– Lightness Races in Orbit
Dec 11 '18 at 16:21
5
@LightnessRacesinOrbit It does - butA
is an array of const, socv A
is still an array of const. I don't think we want to maintain constness, hence Core issue.
– Barry
Dec 11 '18 at 16:25
Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 '18 at 16:56
add a comment |
The wording of the standard in [dcl.struct.bind] says:
If the assignment-expression in the initializer has array type
A
and no ref-qualifier is present,e
has type cvA
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
We have auto [i,j] = ar;
, ar
has array type const int[2]
, and the wording of the standard makes it clear that e
has type const int[2]
. Thus, per the wording, each binding references the element type - which is const int
. Clang is technically correct.
However, as Richard Smith points out in gcc bug 80649:
I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
That seems right. When you write auto x = y;
you'd certainly expect x
to not be top-level const
, but here we have a situation where it still is. I don't think there's a Core issue open for this yet, but there should be.
The cv-qualification cv comes from the decl-specifier-seq ("auto
") not the initialiser ("ar
"), no? Unless it's saying that the qualifiers onA
are merged into cv. But I don't follow why that would be the case; without a ref-qualifier, why would it want to maintain constness? It doesn't do that anywhere else.
– Lightness Races in Orbit
Dec 11 '18 at 16:21
5
@LightnessRacesinOrbit It does - butA
is an array of const, socv A
is still an array of const. I don't think we want to maintain constness, hence Core issue.
– Barry
Dec 11 '18 at 16:25
Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 '18 at 16:56
add a comment |
The wording of the standard in [dcl.struct.bind] says:
If the assignment-expression in the initializer has array type
A
and no ref-qualifier is present,e
has type cvA
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
We have auto [i,j] = ar;
, ar
has array type const int[2]
, and the wording of the standard makes it clear that e
has type const int[2]
. Thus, per the wording, each binding references the element type - which is const int
. Clang is technically correct.
However, as Richard Smith points out in gcc bug 80649:
I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
That seems right. When you write auto x = y;
you'd certainly expect x
to not be top-level const
, but here we have a situation where it still is. I don't think there's a Core issue open for this yet, but there should be.
The wording of the standard in [dcl.struct.bind] says:
If the assignment-expression in the initializer has array type
A
and no ref-qualifier is present,e
has type cvA
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
We have auto [i,j] = ar;
, ar
has array type const int[2]
, and the wording of the standard makes it clear that e
has type const int[2]
. Thus, per the wording, each binding references the element type - which is const int
. Clang is technically correct.
However, as Richard Smith points out in gcc bug 80649:
I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
That seems right. When you write auto x = y;
you'd certainly expect x
to not be top-level const
, but here we have a situation where it still is. I don't think there's a Core issue open for this yet, but there should be.
answered Dec 11 '18 at 15:32
BarryBarry
178k18307563
178k18307563
The cv-qualification cv comes from the decl-specifier-seq ("auto
") not the initialiser ("ar
"), no? Unless it's saying that the qualifiers onA
are merged into cv. But I don't follow why that would be the case; without a ref-qualifier, why would it want to maintain constness? It doesn't do that anywhere else.
– Lightness Races in Orbit
Dec 11 '18 at 16:21
5
@LightnessRacesinOrbit It does - butA
is an array of const, socv A
is still an array of const. I don't think we want to maintain constness, hence Core issue.
– Barry
Dec 11 '18 at 16:25
Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 '18 at 16:56
add a comment |
The cv-qualification cv comes from the decl-specifier-seq ("auto
") not the initialiser ("ar
"), no? Unless it's saying that the qualifiers onA
are merged into cv. But I don't follow why that would be the case; without a ref-qualifier, why would it want to maintain constness? It doesn't do that anywhere else.
– Lightness Races in Orbit
Dec 11 '18 at 16:21
5
@LightnessRacesinOrbit It does - butA
is an array of const, socv A
is still an array of const. I don't think we want to maintain constness, hence Core issue.
– Barry
Dec 11 '18 at 16:25
Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 '18 at 16:56
The cv-qualification cv comes from the decl-specifier-seq ("
auto
") not the initialiser ("ar
"), no? Unless it's saying that the qualifiers on A
are merged into cv. But I don't follow why that would be the case; without a ref-qualifier, why would it want to maintain constness? It doesn't do that anywhere else.– Lightness Races in Orbit
Dec 11 '18 at 16:21
The cv-qualification cv comes from the decl-specifier-seq ("
auto
") not the initialiser ("ar
"), no? Unless it's saying that the qualifiers on A
are merged into cv. But I don't follow why that would be the case; without a ref-qualifier, why would it want to maintain constness? It doesn't do that anywhere else.– Lightness Races in Orbit
Dec 11 '18 at 16:21
5
5
@LightnessRacesinOrbit It does - but
A
is an array of const, so cv A
is still an array of const. I don't think we want to maintain constness, hence Core issue.– Barry
Dec 11 '18 at 16:25
@LightnessRacesinOrbit It does - but
A
is an array of const, so cv A
is still an array of const. I don't think we want to maintain constness, hence Core issue.– Barry
Dec 11 '18 at 16:25
Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 '18 at 16:56
Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 '18 at 16:56
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53726135%2fshall-structured-binding-to-a-copy-of-a-const-c-array-be-const%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
Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 '18 at 14:44
3
gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 '18 at 14:59