是否可以检测对象是否是成员函数内的临时对象?

Cor*_*sto 6 c++ rvalue temporary-objects

我正在使用指向实现的成语实现不可变对象上的装饰器模式.基本上我的设置看起来像这样

struct Object : ObjectBase {
     void doSmth() override {
         impl->doSmth();
     }
     // this is the function I'd like to implement
     Object decorateWith(std::unique_ptr<ObjectDecorator>&&);
private:
     std::unique_ptr<ObjectBase> impl;
};

struct ObjectDecorator : ObjectBase {
    void doSmth() override {
        // do some stuff
        impl->doSmth();
        // do some more stuff
    }
private:
    std::unique_ptr<ObjectBase> impl;
};
Run Code Online (Sandbox Code Playgroud)

这里,decorateWith函数应该具有不同的行为,这取决于它是否是callen on的对象是否是临时的.如果在非临时对象上调用它,它应该返回一个新的Object实例,我必须在其中创建当前Object的深层副本并将其存储在装饰器的unique_ptr中,同时新的Object本身的impl指针指着装饰者.但是,如果在临时调用decorateWith,则只需创建一个ObjectDecorator,只需将当前对象的impl指针移动到装饰器的impl指针中,然后让对象指向新的装饰器即可.

为了阻止我需要一种方法来确定从decorateWith中调用对象是否是临时的,然后根据该检查的结果使用tag-dispatch.那可能吗?

最好的Xodion

编辑:示例调用者代码可能如下所示:

  • decorateWith是在非临时的上调用的

    int main() {
        Object x{};
    
        // this call does not modify x so it can be reused later
        Object y = x.decorateWith{std::make_unique<ObjectDecorator>()};
        y.doSmth();
    
        // do some other stuff here
    
        // here, if I had moved the impl-unique_ptr in the decorateWith
        // call this would now segfault since I'd call nullptr->doSmth();
        x.doSmth();
    
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • decorateWith是临时调用的

    int main() {
        Object x = Object{}.decorateWith(std::make_unique<ObjectDecorator>())
                           .decorateWith(std::make_unique<ObjectDecorator>())
                           .decorateWith(std::make_unique<ObjectDecorator>());
         // in this case it would be unneccessary to make a deep copy of all
         // previous instances so I'd like to only move the impl poiner every time
         x.doSmth()
     }
    
    Run Code Online (Sandbox Code Playgroud)

kmd*_*eko 13

您可以在成员函数上使用ref限定符.来自en.cppreference.com的复制示例

#include <iostream>
struct S {
    void f() & { std::cout << "lvalue\n"; }
    void f() &&{ std::cout << "rvalue\n"; }
};

int main(){
    S s;
    s.f();            // prints "lvalue"
    std::move(s).f(); // prints "rvalue"
    S().f();          // prints "rvalue"
}
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,你会想要这样的东西

 Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &;
 Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &&;
Run Code Online (Sandbox Code Playgroud)