lambda - 如何在移动预期情况下检测意外副本
问题描述
当我使用 lambda 表达式时,有时我会移动捕获可复制和可移动的对象。在我下面的例子中,对象是t
并且它的类型是tracer
. 在 lambda 表达式中,我想t
再次移动到其他函数f()
。f()
的参数是按值传递的,因为我想同时支持复制和移动f()
。
main()
我调用的第一部分,f(std::move(t))
但它没有被移动而是被复制,因为t
它被捕获为 const 变量。函数的第二部分main()
,我添加到mutable
lambda 表达式中。它按我的预期工作。
我经常忘记添加mutable
到 lambda 表达式。如果t
是仅移动类型,则第一种情况会导致编译错误。我很容易注意到这个问题。但如果t
是可复制和可移动的,我很难注意到意外的复制。我想检查那个案子。
有什么好办法吗?
#include <iostream>
struct tracer {
tracer() {
std::cout << __PRETTY_FUNCTION__ << ":" << this << std::endl;
}
~tracer() {
std::cout << __PRETTY_FUNCTION__ << ":" << this << std::endl;
}
tracer(tracer const& other) {
std::cout << __PRETTY_FUNCTION__ << ":" << this << " <- " << &other << std::endl;
}
tracer(tracer&& other) {
std::cout << __PRETTY_FUNCTION__ << ":" << this << " <- " << &other << std::endl;
}
tracer& operator=(tracer const& other) {
std::cout << __PRETTY_FUNCTION__ << ":" << this << " <- " << &other << std::endl;
return *this;
}
tracer& operator=(tracer&& other) {
std::cout << __PRETTY_FUNCTION__ << ":" << this << " <- " << &other << std::endl;
return *this;
}
};
void f(tracer) {
}
int main() {
{
tracer t;
// move assign capture
[t = std::move(t)] { // forget write mutable
f(std::move(t)); // I expect move but copy due to lack of mutable
}();
}
std::cout << "---" << std::endl;
{
tracer t;
// move assign capture
[t = std::move(t)] () mutable {
f(std::move(t)); // Moved as I expected
}();
}
}
解决方案
我想我想出了一个解决方案。我为std::move()
.
template <typename T>
typename std::remove_reference_t<T>&&
only_move(T&& t) {
static_assert(!std::is_const_v<std::remove_reference_t<T>>, "T is const. Fallback to copy.");
return std::move(t);
}
我替换std::move()
为only_move()
如下:
int main() {
{
tracer t;
// move assign capture
[t = only_move(t)] { // got static assertion failed *1
f(only_move(t)); // I expect move but copy due to lack of mutable
}();
}
std::cout << "---" << std::endl;
{
tracer t;
// move assign capture
[t = only_move(t)] () mutable {
f(only_move(t)); // Moved as I expected
}();
}
}
然后我只有在忘记时才会收到静态断言失败消息mutable
。
*1 错误:由于要求 '!std::is_const_v',static_assert 失败“T 是 const。回退到复制。
推荐阅读
- git - 已还原时不显示任何提交?
- node.js - 使用 npm run start 后的 npm elifecycle err
- javascript - 如何让过滤器/查找方法在 javascript 中返回对象字段
- google-app-engine - 为什么没有流量时没有关闭空闲实例?
- intellij-idea - PsiElement 上的 getReference() 始终返回空值
- php - MySQL 语句在 PHP 中不起作用,但在 MySQL Workbench 中运行良好
- c# - 关闭应用程序时的 UWP 进程内后台任务
- javascript - dbms_crypto 和 CryptoJS.HmacSHA256 返回不同的输出
- java - 用于异型 json Java 的 Json 反序列化
- php - 将php转换为bash脚本?