对const c-array副本的结构化绑定是const吗?

Oli*_*liv 26 c++ language-lawyer c++17 structured-bindings

考虑这段代码(演示):

#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?)
    }
Run Code Online (Sandbox Code Playgroud)

结构化结合到一个副本const的c-阵列被声明常量由锵和非const由GCC.

GCC对c阵列的行为与聚合或类似元组类型的行为一致.

另一方面,从我对标准的阅读中,我认为Clang遵循所写的内容.在[dcl.struct.bind]/1中, e具有类型cv A,其中A是初始化表达式的类型,cv是结构化绑定声明的cv限定符.并且初始化表达式的类型ar相应于[expr.type]/1 const int[2].

应该期待什么?我的观点是Clang遵循标准.另一方面,我觉得意图是数组,聚合和元组类型的行为是等价的.

Bar*_*rry 19

[dcl.struct.bind]中标准的措辞说:

如果分配表达初始化具有阵列型A和无REF-限定符存在时,e有一个类型CV A和每个元素是副本初始化或直接初始化来自的对应元素赋值表达式由形式为指定初始化.

我们有auto [i,j] = ar;,ar有数组类型const int[2],标准的措辞明确表示e有类型const int[2].因此,根据措辞,每个绑定引用元素类型 - 即const int.Clang在技术上是正确的.

但是,正如Richard Smith在gcc bug 80649中指出的那样:

我认为这是标准中的一个错误.应该丢弃数组类型的cv限定符,因为它们适用于任何正常的自动推导.

这似乎是正确的.当你写作时,auto x = y;你当然希望x不是顶级的const,但在这里我们仍然存在这样的情况.我认为还没有核心问题,但应该有.

  • @LightnessRacesinOrbit它确实 - 但是`A`是一个const数组,所以`cv A`仍然是一个const数组.我认为我们不想维持常量,因此核心问题. (5认同)