¿Se permiten expresiones obligatorias para "capturar" variables del ámbito de inclusión?

10

En el siguiente ejemplo, los argumentos de la función se usan para probar con una expresión obligatoria si una expresión que los usa está bien formada. La expresión requiere no toma argumentos; utiliza las variables en el alcance de la función directamente:

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

El código anterior se compila con la rama de conceptos de Clang. Sin embargo, GCC10 solo acepta la llamada a Resize. GCC9 ICE. ¿Clang tiene razón al aceptarlo?

metalfox
fuente
2
ICE siempre es un problema del compilador.
Jarod42
Yo diría que, o bien se debe rechazar de código si no se le permite capturar variable local (por lo tanto Resize, y Eziserdebe ser rechazar) o ambas funciones debe compilar. Yo diría que el sonido metálico es correcto.
Jarod42
@ Jarod42 Sí. El comportamiento del CCG es claramente defectuoso. Presentaré un PR. También creo que Clang tiene razón, pero me gustaría confirmar.
metalfox

Respuestas:

6

Sí, una expresión requerida puede usar cualquier cosa que esté dentro del alcance. Después de todo, solo necesita el tipo de cualquier cosa que nombre, excepto en un requisito anidado u otra expresión constante. Eso es cierto tanto para las declaraciones circundantes como para sus propios parámetros (formales).

[expr.prim.req] / 5 :

El cuerpo del requisito contiene una secuencia de requisitos . Estos requisitos pueden referirse a parámetros locales, parámetros de plantilla y cualquier otra declaración visible desde el contexto adjunto.

Arenque Davis
fuente