我有一些代码,其中非泛型lamba表达式具有局部静态变量:临界区的互斥锁.可以简化为:
int i = 0;
auto lambda = [&i](int &v)
{
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
/* critical section with v and i */};
}
Run Code Online (Sandbox Code Playgroud)
现在,在这个lambda表达式实现的关键部分可以逐字其他类型的比重用int &和我也喜欢如更换简单改变int与auto在声明符,就像这样:
auto lambda = [&i](auto &v)
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果我这样做,lambda(int&)并且lambda(float&)将不再共享相同的本地静态变量,这将破坏关键部分中的锁定.
满足所有这些要求的代码中最简单的变化是什么:
一个可行的解决方案是用类模板方法替换lambda表达式,如下所示:
class Lambda
{
public:
Lambda(int &i) : i_(i) {}
template<class V>
void operator()(V &v)
{
std::lock_guard<std::mutex> lock(mutex_);
/* critical section with v and i_ */
};
private:
static std::mutex mutex_;
int &i_;
};
std::mutex Lambda::mutex_;
int i = 0;
Lambda lambda(i);
Run Code Online (Sandbox Code Playgroud)
这可以工作(像私人引用这样的警告i_),但与初始lambda表达式相比,它看起来非常麻烦.会有更直接的事情吗?
您可以初始捕获shared_ptr,这类似于将其定义为闭包类型的成员变量,因此闭包对象的所有副本将共享相同的互斥锁:
auto lambda = [&i, m = std::make_shared<std::mutex>()](auto &v)
{
std::lock_guard<std::mutex> lock(*m);
/* critical section with v and i */
};
Run Code Online (Sandbox Code Playgroud)