Referencia local a std::cout capturado por lambda sin pedirlo

2 minutos de lectura

avatar de usuario
Carreras de ligereza en órbita

¿He perdido la cabeza? ¿Esto siempre estuvo permitido?

#include <iostream>

int main()
{
    auto& os = std::cout;

    auto write = []()
    {
        os << "what\n";
    };

    write();
}

Estoy usando:

Apple LLVM versión 10.0.0 (clang-1000.10.44.4)
Objetivo: x86_64-apple-darwin17.7.0

Aunque también ver en Coliru:

(demo en vivo)

Siempre pensé que una captura vacía no capturaría nada.

De hecho, MSDN dice:

Una cláusula de captura vacía, [ ]indica que el cuerpo de la expresión lambda no accede a variables en el ámbito adjunto.

Investigaciones posteriores sugieren que, de hecho, esto está bien para capturar const cosas (que yo tampoco sabía, pero como sea), pero os no es const (¡No hay referencia! Aunque es inmutable…).

Me encontré con esto al encender -Wextra y notando que Clang pensó un &os la captura (que está presente en mi código real) era innecesaria. Al quitarlo, me quedé asombrado al encontrar que la construcción funcionó.

  • posible duplicado: stackoverflow.com/questions/43827651/…

    – papagaga

    21 de noviembre de 2018 a las 15:26

  • Extrañamente funciona con gcc 8.2…

    – Matthieu Brucher

    21 de noviembre de 2018 a las 15:27

  • Interesante. Esto parece un error de optimización, donde el compilador “ve a través” de la referencia antes de asegurarse de que la referencia en sí está bien para usar.

    – Quintín

    21/11/2018 a las 15:30

  • Hay una informe de defectos abierto cubriendo ese caso y parece no restringido para std::cout

    – enero

    21 de noviembre de 2018 a las 15:56


  • @Jans y eso es digno de una respuesta.

    – SergeyA

    21 de noviembre de 2018 a las 16:07

avatar de usuario
ene

hay un abierto informe de sonido que cubren el caso de captura implícita de referencias por expresiones lambda, esto no se limita a std::cout sino a referencias variables que se encuentran para referirse a expresiones constantes.

Para más referencia, el informe de defectos de respaldo en el CWG es CWG-1472

EDITAR:

Según el comentario de @Rakete1111, debería haber señalado explícitamente que clang tiene razón al aceptar el código, que es el resultado de aplicar el defecto de CWG mencionado anteriormente. El informe se reabrió por la ubicación del diagnóstico, no porque se equivocaron en la aceptación.

  • ¡Ese es el tejón! Gracias Jans.

    – Carreras de ligereza en órbita

    21 de noviembre de 2018 a las 17:21


  • ¿Estás insinuando que clang está mal al aceptar el código?

    – Rakete1111

    22 de noviembre de 2018 a las 6:33

  • @ Rakete1111 No, como dijo Richard en el informe, cuando se encuentra que la variable de referencia se refiere a una expresión constante, la variable a la que se hace referencia se usa en lugar de la variable de referencia en sí, el problema se reabrió por la ubicación del diagnóstico, no porque estaban equivocados sobre la referencia .

    – enero

    22 de noviembre de 2018 a las 14:51


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad