Les expressions require sont-elles autorisées à «capturer» les variables de la portée englobante?

10

Dans l'exemple suivant, les arguments de fonction sont utilisés pour tester avec une expression require si une expression les utilisant est bien formée. L'expression require ne prend aucun argument; il utilise directement les variables de la portée de la fonction:

#include <cstddef>
#include <vector>

template<typename T>
void Resize(T &v, std::size_t const n)
{
  if constexpr (requires { v.resize(n); })
    v.resize(n);
}

template<typename T>
void Eziser(T &v, std::size_t const n)
{
  if constexpr (requires { v.eziser(n); })
    v.eziser(n);
}

int main()
{
  std::vector<int> v;

  Resize(v, 10u);
  Eziser(v, 10u);
}

Le code ci-dessus se compile avec la branche Clang concepts. Cependant, GCC10 accepte uniquement l'appel à Resize. ICE GCC9. Clang a-t-il raison de l'accepter?

metalfox
la source
2
ICE est toujours un problème de compilation.
Jarod42
Je dirais que soit il devrait rejeter le code s'il n'est pas autorisé à capturer la variable locale (donc les deux Resizeet Eziserdoivent être rejetés) ou les deux fonctions devraient être compilées. Je dirais que clang a raison.
Jarod42
@ Jarod42 Oui. Le comportement de GCC est clairement bogué. Je vais déposer un PR. Je pense aussi que Clang a raison, mais je voudrais confirmer.
metalfox

Réponses:

6

Oui, une expression require peut utiliser tout ce qui est dans la portée. Il n'a besoin que du type de tout ce qu'il nomme, après tout, sauf dans une exigence imbriquée ou une autre expression constante. Cela vaut autant pour les déclarations environnantes que pour ses propres paramètres (formels).

[expr.prim.req] / 5 :

Le corps de l'exigence contient une séquence d' exigences . Ces exigences peuvent faire référence à des paramètres locaux, à des paramètres de modèle et à toute autre déclaration visible à partir du contexte englobant.

Davis Herring
la source