Shall structured binding to a copy of a const c-array be const?












26














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.










share|improve this question




















  • 1




    Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
    – Daniel Langr
    Dec 11 at 14:44








  • 3




    gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
    – cpplearner
    Dec 11 at 14:59
















26














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.










share|improve this question




















  • 1




    Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
    – Daniel Langr
    Dec 11 at 14:44








  • 3




    gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
    – cpplearner
    Dec 11 at 14:59














26












26








26


4





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.










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 11 at 14:27

























asked Dec 11 at 14:21









Oliv

8,2501955




8,2501955








  • 1




    Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
    – Daniel Langr
    Dec 11 at 14:44








  • 3




    gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
    – cpplearner
    Dec 11 at 14:59














  • 1




    Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
    – Daniel Langr
    Dec 11 at 14:44








  • 3




    gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
    – cpplearner
    Dec 11 at 14:59








1




1




Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 at 14:44






Isn't this note related: eel.is/c++draft/dcl.struct.bind#3.note-1?
– Daniel Langr
Dec 11 at 14:44






3




3




gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 at 14:59




gcc.gnu.org/bugzilla/show_bug.cgi?id=86049
– cpplearner
Dec 11 at 14:59












1 Answer
1






active

oldest

votes


















19














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 cv A 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.






share|improve this answer





















  • 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 at 16:21








  • 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 at 16:25










  • Mm, I could be persuaded by that.
    – Lightness Races in Orbit
    Dec 11 at 16:56











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
});


}
});














draft saved

draft discarded


















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









19














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 cv A 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.






share|improve this answer





















  • 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 at 16:21








  • 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 at 16:25










  • Mm, I could be persuaded by that.
    – Lightness Races in Orbit
    Dec 11 at 16:56
















19














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 cv A 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.






share|improve this answer





















  • 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 at 16:21








  • 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 at 16:25










  • Mm, I could be persuaded by that.
    – Lightness Races in Orbit
    Dec 11 at 16:56














19












19








19






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 cv A 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.






share|improve this answer












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 cv A 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.







share|improve this answer












share|improve this answer



share|improve this answer










answered Dec 11 at 15:32









Barry

177k18304558




177k18304558












  • 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 at 16:21








  • 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 at 16:25










  • Mm, I could be persuaded by that.
    – Lightness Races in Orbit
    Dec 11 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 at 16:21








  • 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 at 16:25










  • Mm, I could be persuaded by that.
    – Lightness Races in Orbit
    Dec 11 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 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 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 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 at 16:25












Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 at 16:56




Mm, I could be persuaded by that.
– Lightness Races in Orbit
Dec 11 at 16:56


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?