web-dev-qa-db-fra.com

La liaison structurée à une copie d'un tableau c const doit-elle être const?

Considérez ce code ( démo ):

#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?)
    }

Une liaison structurée à une copie d'un const c-array est déclarée const par Clang et non const par GCC.

Le comportement de GCC pour c-array est cohérent avec le comportement observé pour les types d'agrégat ou de type Tuple.

Par contre, d'après ma lecture de la norme, je suppose que Clang suit ce qui est écrit. Dans [dcl.struct.bind]/1 e a le type cv A où A est le type de l'expression d'initialisation et le cv est le qualificatif cv de la déclaration de liaison structurée. Et le type de l'expression d'initialisation ar est en conséquence [expr.type]/1const int[2].

Que faut-il attendre? Mon opinion est que Clang suit la norme. D'un autre côté, je pense que l'intention était que les comportements des types tableau, agrégat et Tuple soient équivalents.

26
Oliv

Le libellé de la norme dans [dcl.struct.bind] dit:

Si l'expression d'affectation dans l'initialiseur a le type de tableau A et aucun ref-qualifier est présent, e a le type cv A et chaque élément est initialisé en copie ou initialisé directement à partir de l'élément correspondant de expression-affectation comme spécifié par la forme de l'initialiseur .

Nous avons auto [i,j] = ar;, ar a un type de tableau const int[2], et le libellé de la norme indique clairement que e a le type const int[2]. Ainsi, selon le libellé , chaque liaison fait référence au type d'élément - qui est const int. Clang est techniquement correct.

Cependant, comme le souligne Richard Smith dans bogue gcc 80649 :

Je pense que c'est un bug dans la norme. Les qualificatifs cv du type tableau doivent être supprimés, comme ils le seraient pour toute déduction automatique normale.

Cela me semble juste. Lorsque vous écrivez auto x = y; vous vous attendez certainement à ce que x ne soit pas de niveau supérieur const, mais nous avons ici une situation où il l'est toujours. Je ne pense pas qu'il y ait encore un problème fondamental pour cela, mais il devrait y en avoir.

19
Barry