La validez de la expresión lambda con la lista de parámetros omitidos en C++23

4 minutos de lectura

avatar de usuario
康桓瑋

De acuerdo a preferencia cptanto gcc como clang han completado la implementación de P1102R2 (“Abajo con ()!”) recientemente, lo que significa que podemos definir expresiones lambda de forma más concisa en C++23.

Pero descubrí que son inconsistentes con cierta forma:

auto l = []<auto> noexcept requires true {};

clang acepta este formulario y gcc rechaza su gramática.

¿En qué compilador debo confiar? ¿Esta lambda está bien formada o mal formada en C++ 23?

Actualizar:

Tal vez debido a la presión de la opinión pública, clang arregló rápidamente el 49736 dentro de los cinco días posteriores a la denuncia.

Mientras intentaba más, descubrí accidentalmente que gcc también rechazó el siguiente formulario válido, lo que me hizo informar el 99850 y se arregló después de 2 semanas.

auto l = []<auto> requires true -> void {};

  • No parece que esta lambda tenga ninguna aplicación en la vida real. Agregar la etiqueta de abogado de idiomas es probablemente una buena idea.

    – súper

    27 de marzo de 2021 a las 16:06

  • No confiaría en la implementación de ninguna característica de C++23 de un compilador que ni siquiera haya terminado C++20. Además, ¿qué opción de línea de comando usaría para acceder a ella?

    – Nicolás Bolas

    27 de marzo de 2021 a las 16:11

  • @NicolBolas GCC y Clang trunk entienden -std=c++2b.

    – Santo Gato Negro

    27 de marzo de 2021 a las 16:15


  • “Tal vez por la presión de la opinión pública” — +1 solo por esa broma.

    – Yakk – Adam Nevraumont

    6 de agosto de 2021 a las 19:52

avatar de usuario
barry

Gracias por recordarme lo inútil que es esta función.

La respuesta correcta es: no, esa no es una lambda bien formada. La gramática se define en [expr.prim.lambda.general]:

ingrese la descripción de la imagen aquí

En nuestro caso, para empezar tenemos:

[]<auto> noexcept requires true {};
  • [] es el introductor lambda
  • <auto> partidos <template-parameter-list> y ahora sabemos que somos el segundo tipo expresión lambda. Entonces, gramaticalmente, debemos seguir con un requiere cláusula (opcionalmente) luego un lambda-declarator Entonces un declaración compuesta.
  • noexcept no coincide requiere cláusulaasí que ahora estamos analizando un lambda-declarator. A lambda-declarator podría empezar con (parameter-declaration-clause) pero no tenemos eso, así que solo estamos buscando especificadores lambda. Consumimos el noexcept como parte de noexcept-especificador.
  • requires true tampoco encaja atributo-especificador-seq o tipo de retorno final así que no tenemos ninguno de esos, y ahora hemos terminado con especificadores lambda así que hemos terminado con lambda-declarator. En este punto, estamos buscando un declaración compuesta. Pero no tenemos eso, así que esto es un error.

Básicamente, hay dos lugares donde puedes poner un requiere cláusula: ya sea directamente después de los parámetros de la plantilla o, si tenemos parámetros de funcióndespués de la especificadores lambda después de los parámetros de la función. Así que esto funciona:

[]<auto> requires true noexcept {};

como hace esto:

[]<auto>() noexcept requires true {};

como hace esto:

[]<auto> requires true () noexcept requires true { };

Pero no el de OP.

Además, no escribas esto.

  • presenté un informe de error para llvm esta mañana, pero no estoy 100% seguro de que deba estar mal formado. Gracias por hacerme saber que tengo razón.

    – 康桓瑋

    27 de marzo de 2021 a las 17:41

  • Un punto adicional: ¿Hacerlo definido eliminaría una verruga, haciendo que el lenguaje sea más regular, y debería definirse así? Sin embargo, los ejemplos inventados que son inventados no son tan sorprendentes.

    – Deduplicador

    28 de marzo de 2021 a las 17:52

  • @Deduplicator ¿Debería? Quiero decir, si estás en el punto en el que ya estás escribiendo parámetros de plantilla y un especificador noexcept y una cláusula requiere, ¿está realmente perjudicado por tener que proporcionar una cláusula adicional? ()?

    – Barry

    28 de marzo de 2021 a las 19:03

  • @Deduplicator: simplemente no se consideró que valiera la pena hacer una gramática complicada para hacer un no vacío especificadores lambda diferenciar los dos potenciales requiere cláusulas.

    – Davis arenque

    29 de marzo de 2021 a las 2:46

  • La observación que condujo a la regla actual es que la cláusula require restringe la lista de parámetros de plantilla explícita o la lista de parámetros de función explícita. Como tal, un explícito <> lista puede ir seguida de una cláusula requiere y una cláusula explícita () la lista puede ir seguida de una cláusula requiere. Si omite la lista explícita, no puede incluir una cláusula require para ella.

    – Ricardo Smith

    30 de marzo de 2021 a las 5:29

¿Ha sido útil esta solución?