funciones examples c++ c++11 lambda visual-studio-2013 language-lawyer

examples - ¿Requiere C++ 11 que este lambda se declare mutable?



lambda examples c++ (2)

Considere este código C ++ 11:

#include <functional> #include <cstdlib> template <typename F> void test(F &&f) { auto foo = [f]() { f(); }; foo(); } int main() { test(std::bind(std::puts, "hello")); return 0; }

GCC y Clang aceptan esto como código válido de C ++ 11, pero Visual Studio 2013 requiere que la lambda se declare mutable ( auto foo = [f]() mutable { ... } ). De lo contrario, me sale este error:

error C3848: expresión que tiene el tipo '' const std::_Bind<true,int,int (__cdecl *const )(const char *),const char (&)[6]> '' perdería algunos calificadores const-volátiles para llamar '' int std::_Bind<true,int,int (__cdecl *const )(const char *),const char (&)[6]>::operator ()<>(void) ''

¿Visual Studio tiene derecho a rechazar este código sin mutable, o es válido C ++ 11?

(Curiosamente Clang rechaza el código si cambia std::bind(std::puts, "hello") std::bind(std::exit, 0) aparentemente a std::bind(std::exit, 0) aparentemente porque considera que noreturn hará que la función escriba diferente; I '' Estoy bastante seguro de que esto es un error.)


Esto no es realmente sobre lambdas.

#include <functional> #include <cstdlib> int main() { const auto x = std::bind(std::puts, "hello"); x(); }

Esto es aceptado por GCC, pero rechazado por MSVC.

El estándar no está claro si esto es válido, IMO. El valor de retorno g de std::bind tiene un tipo de retorno no especificado para el que g(...) es válido y se define en términos de los cv-calificadores de g , pero el estándar no dice realmente que ningún operator() deba ser invocable para objetos o referencias const . Esto implica fuertemente que esto tiene la intención de ser válido, porque de lo contrario la referencia a los cv-calificadores de g parece inútil, pero en realidad no dice que sea válida.

Por eso, creo que el comportamiento de MSVC no es lo que los autores de la norma pretendían, pero de todos modos puede ajustarse a lo que exige la norma.


Esto parece un error en la implementación de bind de Visual Studio, que devuelve un tipo con un operador de llamada de función no const. Debería devolver un tipo que reenvía todas las llamadas de función al objeto de función enlazado, independientemente de sus propias calificaciones cv.

Para resumir el lenguaje bastante opaco de C ++ 11 20.8.9.1.2, las llamadas de función al resultado de bind deben reenviarse al objeto de función enlazado, por lo que deberían permitirse si se permitieran llamadas a ese objeto. Por lo tanto, sería un error si el objeto de la función enlazada no fuera invocable si const ; pero aquí, al ser un puntero de función, se puede llamar independientemente de las calificaciones de cv.