Reputation: 7592
The following code in VS2010:
void AddBishopMoves( vector<Move> &moves, uint64_t mask, uint64_t occupied, uint64_t valid )
{
ForEachBit( mask, [&moves,occupied,valid]( Square from )
{
auto toMask = BishopAttacks( from, occupied ) & valid;
ForEachBit( toMask, [&moves, from]( Square to )
{
moves.push_back( Move( from, to ) );
});
});
}
gives the error
error C3480: '`anonymous-namespace'::::moves': a lambda capture variable must be from an enclosing function scope
But i did capture "moves" by reference in the outer lambda.
Changing the code to assign moves to a temporary and capturing the temporary solves the error. This gives no error in VS2010:
void AddBishopMoves( vector<Move> &moves, uint64_t mask, uint64_t occupied, uint64_t valid )
{
ForEachBit( mask, [&moves,occupied,valid]( Square from )
{
auto& x = moves;
auto toMask = BishopAttacks( from, occupied ) & valid;
ForEachBit( toMask, [&x, from]( Square to )
{
x.push_back( Move( from, to ) );
});
});
}
The question is why?
Am I avoiding some subtle bug in logic the compiler is trying to warn me about? Is this just not supported by c++11 capture semantics? Or is this just a bugged feature?
Upvotes: 2
Views: 457
Reputation: 131789
This is a known bug that seems to have been fixed, albeit too late for the VS11 Beta, as the bug is still present there.
Another simple work-around would be to just implicitly capture the variable in the inner lambda:
void AddBishopMoves( vector<Move> &moves, uint64_t mask, uint64_t occupied, uint64_t valid )
{
ForEachBit( mask, [&moves,occupied,valid]( Square from )
{
auto toMask = BishopAttacks( from, occupied ) & valid;
ForEachBit( toMask, [&, from]( Square to ) // <== implicit capture of 'moves'
{
moves.push_back( Move( from, to ) );
});
});
}
IMHO, you should generally just capture your stuff implicitly by reference, as I don't see any reason to do otherwise here.
Btw, thanks to you I discovered another bug, which may be related. Please upvote if you can.
Upvotes: 2