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 ) );
});
});
}
报错
error C3480: '`anonymous-namespace'::::moves': a lambda capture variable must be from an enclosing function scope
但我确实通过外部 lambda 中的引用捕获了“移动”。
更改代码以将移动分配给临时对象并捕获临时对象可以解决该错误。这在 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 ) );
});
});
}
问题是为什么?
我是否避免了编译器试图警告我的一些微妙的逻辑错误? 这是 c++11 捕获语义不支持的吗? 或者这只是一个有缺陷的功能?
最佳答案
这是a known bug该问题似乎已得到修复,尽管对于 VS11 Beta 来说为时已晚,因为该错误仍然存在。
另一个简单的解决方法是隐式捕获内部 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 ) );
});
});
}
恕我直言,您通常应该通过引用隐式捕获您的内容,因为我认为这里没有任何理由这样做。
顺便说一句,多亏了你我发现了another bug ,这可能是相关的。如果可以的话请点赞。
关于c++ - 从 lambda 捕获中捕获变量会出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9647764/