c++ language-lawyer c++17 structured-bindings

c++ - ¿La unión estructurada a una copia de un const c-array será const?



language-lawyer c++17 (1)

Considere este código ( 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?) }

Un enlace estructurado a una copia de una const c-array se declara const por Clang y non-const por GCC.

El comportamiento de GCC para c-array es consistente con el comportamiento observado para los tipos agregados o similares a tuplas.

Por otro lado, de mi lectura del estándar, supongo que Clang sigue lo que está escrito. En [dcl.struct.bind]/1 e tiene el tipo cv A donde A es el tipo de la expresión inicializadora y el cv es el calificador cv de la declaración de enlace estructurado. Y el tipo de la expresión de inicialización ar es, en consecuencia, de [expr.type]/1 const int[2] .

¿Qué se debe esperar? Mi opinión es que Clang sigue el estándar. Por otro lado, siento que la intención era que los comportamientos para los tipos de matriz, agregados y similares a tuplas fueran equivalentes.


La redacción de la norma en [dcl.struct.bind] dice:

Si la expresión-asignación en el inicializador tiene un tipo de matriz A y no está presente ningún ref-calificador , e tiene el tipo cv A y cada elemento se inicializa con copia o se inicializa directamente desde el elemento correspondiente de la expresión-asignación según lo especifica la forma del inicializador .

Tenemos auto [i,j] = ar; , ar tiene el tipo de matriz const int[2] , y la redacción de la norma deja claro que e tiene el tipo const int[2] . Por lo tanto, de acuerdo con la redacción , cada enlace hace referencia al tipo de elemento, que es const int . Clang es técnicamente correcto.

Sin embargo, como señala Richard Smith en gcc.gnu.org/bugzilla/show_bug.cgi?id=86049 :

Creo que esto es un error en la norma. Los calificadores cv del tipo de matriz deben descartarse, como lo sería para cualquier deducción automática normal.

Eso parece correcto. Cuando escribes auto x = y; ciertamente esperarías que x no sea una const nivel superior, pero aquí tenemos una situación en la que todavía está. No creo que haya un problema de Core abierto para esto todavía, pero debería haberlo.