Рассмотрим этот код (демо):
#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?)
}
Структурированная привязка к копии const
c-массива объявляется const Clang и неконстантной GCC.
Поведение GCC для c-массива согласуется с поведением, наблюдаемым для агрегатных или кортежоподобных типов.
С другой стороны, из моего прочтения стандарта я полагаю, что Clang следует тому, что написано. В [dcl.struct.bind]/1 e имеет тип cv A, где A - тип выражения инициализатора, а cv - cv-квалификатор объявления структурированной привязки. И тип выражения инициализатора ar
соответствует [expr.type]/1 const int[2]
.
Чего следует ожидать? Мое мнение таково, что Clang следует стандарту. С другой стороны, я чувствую, что намерения в том, чтобы поведение для массивов, агрегатов и кортежоподобных типов было эквивалентным.