The following code works with gcc
#include <map>
int main() {
std::map<int, double> dict;
const auto lambda = [&]()
{
decltype(dict)::value_type bar;
};
}
But for msvc I have to 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 I get an 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
Which compiler shows the correct behaviour according to the standard?
update:
For msvc decltype(dict)
really is a reference, as the following code
#include <map>
int main()
{
std::map<int, double> dict;
const auto lambda = [&]()
{
decltype(dict) foo;
};
}
errors with
error C2530: 'foo': references must be initialized
If this really is wrong behaviour, it could lead to nasty bugs, like dangling references when code is compiled with 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
};
}
There is no special rule regarding non parenthesized applications of
decltype
(ie. [expr.prim.lambda]/20 does not apply). So we just fall back to the usual definition ofdecltype
, which mandates that if the operand is an id-expression, the yielded type is just the declared type of the entity, and that's not a reference type. Hence VC++ is wrong.NB: it doesn't matter whether
dict
is captured or not, because ¶17:decltype
never odr-uses any of its operands or suboperands. This rule actually gets pretty problematic at times, e.g. as shown in core issue 958:Here,
decltype(f(i))
uses the non-const
i
from the enclosing scope. However, since the lambda isn'tmutable
, thei
in the body is actuallyconst
, hence the trailing-return-type is incorrect. CWG concluded this arises too infrequently to be worth solving.