c++ - type of reference-captured object inside lambda -
the following code works gcc
#include <map> int main() { std::map<int, double> dict; const auto lambda = [&]() { decltype(dict)::value_type bar; }; }
but msvc have additionally use 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; }; }
otherwise an error:
error c2651: 'std::map<int,double,std::less<_kty>,std::allocator<std::pair<const _kty,_ty>>> &': left of '::' must class, struct or union
which compiler shows correct behaviour according standard?
update:
for msvc decltype(dict)
reference, following code
#include <map> int main() { std::map<int, double> dict; const auto lambda = [&]() { decltype(dict) foo; }; }
errors with
error c2530: 'foo': references must initialized
if wrong behaviour, lead nasty bugs, dangling references when code compiled 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 dangling reference in msvc }; }
there no special rule regarding non parenthesized applications of decltype
(ie. [expr.prim.lambda]/20 not apply). fall usual definition of decltype
, mandates if operand id-expression, yielded type declared type of entity, , that's not reference type. hence vc++ wrong.
nb: doesn't matter whether dict
captured or not, because ¶17:
every id-expression within compound-statement of lambda-expression that odr-use (3.2) of entity captured copy transformed access corresponding unnamed data member of closure type. [ note: an id-expression not odr-use refers original entity, never member of closure type. furthermore, such id-expression not cause implicit capture of entity. — end note ]
decltype
never odr-uses of operands or suboperands. rule gets pretty problematic @ times, e.g. shown in core issue 958:
int f (int&); void* f (const int&); int main() { int i; [=] ()-> decltype(f(i)) { return f(i); }; }
here, decltype(f(i))
uses non-const
i
enclosing scope. however, since lambda isn't mutable
, i
in body const
, hence trailing-return-type incorrect. cwg concluded arises infrequently worth solving.
Comments
Post a Comment