如何在 C++ 中将不可复制的局部变量移出 lambda?

How to move non-copyable local variable out of lambda in C++?

我想实现一个简单的运行时检查宏,所以它的工作方式如下:

CHECK(expr) << "Some problem!";

我为此编写了一个简化的日志记录 class:

class Log {
 public:
  Log() = default;
  Log(const Log&) = delete;

  ~Log() {
    cout << this << " dtor" << endl;
    cout << stream_.str() << endl;
  }

  template <class T>
  Log& operator<<(const T& info) {
    cout << this << " <<" << endl;
    stream_ << info;
    return *this;
  }

 private:
  stringstream stream_;
};

让宏为:

#define CHECK(expr) \
  if (!(expr)) [] { /* See attempts below */ }()

现在让我们尝试实现 lambda。


尝试 #1

最简单的方法应该是:

[] {
  Log log;
  log << "A";
  return log;
}

但是no luck - 复制构造函数被删除:

error: use of deleted function 'Log::Log(const Log&)'

尝试 #2

好的,让我们显式移动局部变量:

[] {
  Log log;
  log << "A";
  return move(log);
}

嗯,还是no luck.

尝试 #3

绝望的尝试当然不应该成功:

[]() -> Log&& {
  Log log;
  log << "A";
  return move(log);
}

它编译甚至 runs,但 operator << 在析构函数之后调用:

0xbfe84064 dtor
A
0xbfe84064 <<

帮我弄清楚我在从 lambda 返回变量时做错了什么?

创建移动构造函数default,即

Log(Log&&) = default;

因为否则存在 user-provided 复制构造函数(即使 deleted)disables the move ctor. You should also return log; instead of return move(log);, as the default move ctor will be invoked (since the copy ctor is deleted). See e.g. this 以了解为什么通常应避免 return move 的更多详细信息。

Live on Coliru