tutorial smart programar para introduccion inteligentes inteligente ejemplos crear contratos contrato c++ lambda language-lawyer decltype

c++ - smart - programar contratos inteligentes



tipo de objeto capturado de referencia dentro de lambda (1)

El siguiente código funciona con gcc

#include <map> int main() { std::map<int, double> dict; const auto lambda = [&]() { decltype(dict)::value_type bar; }; }

Pero para msvc tengo que usar adicionalmente std::remove_reference

#include <map> #include <type_traits> int main() { std::map<int, double> dict; const auto lambda = [&]() { std::remove_reference_t<decltype(dict)>::value_type bar; }; }

De lo contrario me sale un error :

error C2651: ''std::map<int,double,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>> &'': left of ''::'' must be a class, struct or union

¿Qué compilador muestra el comportamiento correcto según el estándar?

actualizar:

Para msvc decltype(dict) realmente es una referencia, como el siguiente código

#include <map> int main() { std::map<int, double> dict; const auto lambda = [&]() { decltype(dict) foo; }; }

errores con

error C2530: ''foo'': references must be initialized

Si este es realmente un comportamiento incorrecto, podría dar lugar a errores desagradables, como referencias colgantes cuando el código se compila con msvc.

#include <map> std::map<int, double> return_a_map() { std::map<int, double> result; return result; } int main() { std::map<int, double> dict; const auto lambda = [&]() { decltype(dict) foo = return_a_map(); // foo is a dangling reference in msvc }; }


No hay una regla especial con respecto a las aplicaciones de paréntesis no entre paréntesis (es decir, [expr.prim.lambda]/20 no se aplica [expr.prim.lambda]/20 ). Por lo tanto, simplemente recurrimos a la definición habitual de decltype , que exige que si el operando es una expresión-id , el tipo decltype es solo el tipo declarado de la entidad, y eso no es un tipo de referencia. Por lo tanto, VC ++ está equivocado.

NB: no importa si el dict se captura o no, porque ¶17 :

Cada id-expresión dentro de la declaración compuesta de una lambda-expresión que es un odr-use (3.2) de una entidad capturada por copia se transforma en un acceso al miembro de datos correspondiente sin nombre del tipo de cierre. [ Nota : una expresión-id que no es un uso de odr se refiere a la entidad original , nunca a un miembro del tipo de cierre. Además, tal expresión-id no causa la captura implícita de la entidad. - nota final ]

decltype nunca odr utiliza ninguno de sus operandos o suboperandos. Esta regla se vuelve bastante problemática a veces, por ejemplo, como se muestra en el problema central 958 :

int f (int&); void* f (const int&); int main() { int i; [=] ()-> decltype(f(i)) { return f(i); }; }

Aquí, decltype(f(i)) usa el non- const i del ámbito que lo incluye. Sin embargo, dado que la lambda no es mutable , la i en el cuerpo es en realidad const , por lo tanto, el tipo de retorno es incorrecto. El CWG concluyó que esto surge con poca frecuencia para que valga la pena resolverlo.