如何在 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 复制构造函数(即使 delete
d)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
的更多详细信息。
我想实现一个简单的运行时检查宏,所以它的工作方式如下:
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 复制构造函数(即使 delete
d)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
的更多详细信息。