将 std::move(*this) 放入从 this->some_method 创建的对象中是否安全?
Is it safe to `std::move(*this)` into an object being created from `this->some_method`?
我正在尝试构建一个稍后可以异步执行的可调用对象链。我想尝试以下方法:构建节点 的 "nested" 结构(通过将每个节点移动到它的 "parent") 导致一个对象存储所有计算并可以按需启动链。
这就是我的想法:
template <typename TParent, typename TF>
struct node
{
TParent _parent;
TF _f;
node(TParent&& parent, TF&& f)
: _parent{std::move(parent)}, _f{std::move(f)}
{
}
template <typename TFContinuation>
auto then(TFContinuation&& f_continuation)
{
using this_type = node<TParent, TF>;
return node<this_type, std::decay_t<TFContinuation>>
{std::move(*this), std::move(f_continuation)};
// ^^^^^^^^^^^^^^^^
// ...safe?
}
};
上面的代码将允许用户编写如下所示的链:
int main()
{
node n{some_root_callable, []{/*...*/}};
n.then([]{/*...*/})
.then([]{/*...*/})
.then([]{/*...*/})
.then([]{/*...*/});
}
(真正的实现会支持更有用的抽象,例如when_all(...)
或when_any(...)
。)
假设TParent
、TF
和TFContinuation
是可移动的可调用对象,是否安全(即明确定义) 在调用 node::then
?
期间调用 std::move(*this)
该代码是否存在问题取决于该代码对其获取的引用做了什么。如果调用的代码将对象变成糊状,那么当它 returns 时,您的代码必须处理已变成糊状的对象。但是,对于从成员函数调用的 any 函数,无论它是使用右值引用、可修改的左值引用、指针还是您可能想要的任何其他机制调用的,都是如此想象一下。
你可以做到,而且很安全。在大多数情况下,它只会让成员处于未定义但有效的状态。话虽如此,移动 this
是安全的,只要您不再尝试使用它的成员。但是对于标准库类型和大多数用户定义的类型,这甚至都不是问题。
有一件事我想改变。我只允许从右值调用:
template <typename TFContinuation> // v-- notice the && here.
auto then(TFContinuation&& f_continuation) && {
using this_type = node<TParent, TF>;
return node<this_type, std::decay_t<TFContinuation>>{
std::move(*this), std::move(f_continuation)
};
}
很棒的是你甚至可以在它不是右值时重载它:
template <typename TFContinuation>
auto then(TFContinuation&& f_continuation) const & {
using this_type = node<TParent, TF>;
return node<this_type, std::decay_t<TFContinuation>>{
*this, std::move(f_continuation)
};
}
我正在尝试构建一个稍后可以异步执行的可调用对象链。我想尝试以下方法:构建节点 的 "nested" 结构(通过将每个节点移动到它的 "parent") 导致一个对象存储所有计算并可以按需启动链。
这就是我的想法:
template <typename TParent, typename TF>
struct node
{
TParent _parent;
TF _f;
node(TParent&& parent, TF&& f)
: _parent{std::move(parent)}, _f{std::move(f)}
{
}
template <typename TFContinuation>
auto then(TFContinuation&& f_continuation)
{
using this_type = node<TParent, TF>;
return node<this_type, std::decay_t<TFContinuation>>
{std::move(*this), std::move(f_continuation)};
// ^^^^^^^^^^^^^^^^
// ...safe?
}
};
上面的代码将允许用户编写如下所示的链:
int main()
{
node n{some_root_callable, []{/*...*/}};
n.then([]{/*...*/})
.then([]{/*...*/})
.then([]{/*...*/})
.then([]{/*...*/});
}
(真正的实现会支持更有用的抽象,例如when_all(...)
或when_any(...)
。)
假设TParent
、TF
和TFContinuation
是可移动的可调用对象,是否安全(即明确定义) 在调用 node::then
?
std::move(*this)
该代码是否存在问题取决于该代码对其获取的引用做了什么。如果调用的代码将对象变成糊状,那么当它 returns 时,您的代码必须处理已变成糊状的对象。但是,对于从成员函数调用的 any 函数,无论它是使用右值引用、可修改的左值引用、指针还是您可能想要的任何其他机制调用的,都是如此想象一下。
你可以做到,而且很安全。在大多数情况下,它只会让成员处于未定义但有效的状态。话虽如此,移动 this
是安全的,只要您不再尝试使用它的成员。但是对于标准库类型和大多数用户定义的类型,这甚至都不是问题。
有一件事我想改变。我只允许从右值调用:
template <typename TFContinuation> // v-- notice the && here.
auto then(TFContinuation&& f_continuation) && {
using this_type = node<TParent, TF>;
return node<this_type, std::decay_t<TFContinuation>>{
std::move(*this), std::move(f_continuation)
};
}
很棒的是你甚至可以在它不是右值时重载它:
template <typename TFContinuation>
auto then(TFContinuation&& f_continuation) const & {
using this_type = node<TParent, TF>;
return node<this_type, std::decay_t<TFContinuation>>{
*this, std::move(f_continuation)
};
}