MerickOWA
MerickOWA

Reputation: 7592

Capturing a variable from a lambda capture gives an error?

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

Answers (1)

Xeo
Xeo

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

Related Questions