在一般lambda表达式的所有实例化之间共享的局部静态变量

Com*_*czy 5 c++ lambda c++14

我有一些代码,其中非泛型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 &和我也喜欢如更换简单改变intauto在声明符,就像这样:

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表达式相比,它看起来非常麻烦.会有更直接的事情吗?

Jon*_*ely 5

您可以初始捕获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)

  • 这样他就没有*在关键部分*的所有实例中共享一个互斥锁.我错了吗? (2认同)