如何为构造函数生成的右值赋予左值生存期?

时间:2019-04-10 11:13:28

标签: c++

while(model.condition) {
    auto data = yield_data();
    auto _= manipulate(model, data);
    model.get_info(args);
}

我有一个类型为manipulate的RAII对象,其析构函数可以消除它超出范围时引起的突变,就像std::lock_guard一样。问题是用户必须键入auto _=,否则析构函数将在model.get_info()之前被调用;我不喜欢用户必须输入auto _=。用户为什么要考虑创建一个从未使用过的对象?

我的第一个想法是使构造函数[[nodiscard]];但是构造函数没有返回值。有没有办法告诉编译器,操纵右值应具有左值生存期?

4 个答案:

答案 0 :(得分:2)

对于std::lock_guard来说,这也是一个未解决的问题,如果您忘记给它起一个名字,就会得到一个错误。

此处有一些技巧:How to avoid C++ anonymous objects

有关此问题和其他陷阱的讨论,请链接到这里:Different behavior when `std::lock_guard<std::mutex>` object has no name

答案 1 :(得分:1)

如果不将rvalue绑定到某个变量,则无法将rvalue的生存期扩展到超出它的完整表达式的范围。因此,不幸的是,您将不得不以某种方式将右值变成左值,或者将实际工作移到不超过右值的范围内。

实现后者的一种方法是使用回调,如此处其他答案所示。

或者,由于有保证的复制省略,您可以将manipulate()转换为函数,而不必直接调用构造函数。这至少可以让您利用[[nodiscard]]属性,例如:

[[nodiscard]] manipulate begin_transaction(const Model& model, const Data& data)
{
    return { model, data };
}

while(model.condition)
{
    auto data = yield_data();
    auto guard = begin_transaction(model, data);
    model.get_info(args);
}

try it out here

答案 2 :(得分:0)

您必须执行此操作。没有其他选择。

NAG自动微分DCO库就是一个令人痛苦的好例子,您必须在其中向代码添加大量const auto&,因为它们依靠破坏顺序来创建图形(RAII,就像您一样依靠这个。)

可以这样说,甚至使用const auto& _,以确保在需要时不会更改_

答案 3 :(得分:0)

要求用户告诉manipulate ctor他们想运行什么代码。因此,将其更改为以callable作为参数并调用它:

manipulate(model, data, [&model, &args] {
    model.get_info(args);
});
相关问题