2016-06-08 13 views
5

Tôi đang triển khai mẫu trang trí trên các đối tượng không thay đổi với thành ngữ trỏ đến triển khai. Về cơ bản thiết lập của tôi trông như thế nàyCó thể phát hiện xem đối tượng là tạm thời từ bên trong hàm thành viên không?

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; 
}; 

Ở đây, hàm decorateWith được cho là có hành vi khác nhau tùy thuộc vào việc các đối tượng nó được Callen trên là tạm thời hay không. Nếu nó được gọi trên một đối tượng không tạm thời, nó là nghĩa vụ phải trả về một đối tượng Object mới, nơi tôi phải tạo một bản sao sâu của Object hiện tại và lưu nó trong unique_ptr của trang trí trong khi con trỏ impl của Object mới đang trỏ đến trang trí. Nếu, tuy nhiên, decorWith được gọi là tạm thời, nó đủ để tạo ra một ObjectDecorator và chỉ di chuyển con trỏ của đối tượng hiện tại vào con trỏ của trình trang trí và để đối tượng trỏ đến trang trí mới.

Để impelement rằng tôi cần một cách để xác định từ bên trong các cuộc gọi để decorateWith liệu đối tượng là tạm thời hay không và sau đó sử dụng tag-dispatch dựa trên kết quả của kiểm tra đó. Điều đó có thể không?

nhất Xodion

EDIT: Mã gọi mẫu có thể trông như thế này:

  • decorateWith được gọi vào một tổ chức phi tạm

    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(); 
    
    } 
    
  • decorateWith được kêu gọi tạm thời

    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() 
    } 
    
+1

Giải thích của bạn có thể được sao lưu tốt hơn với mã gọi điện mẫu. – kfsone

+2

Bạn có yêu cầu xác định liệu 'Object'' decorate đồ trang trí có được gọi là tạm thời hay không, hoặc nếu đối số 'decorateWith' là tạm thời? – md5i

+0

Tôi muốn có điều kiện di chuyển chỉ khi đối tượng mà trên đó decorate được gọi là tạm thời và tạo một bản sao sâu nếu không, do đó, đó là về cách kiểm tra xem một đối tượng là tạm thời hay không. Như các câu trả lời dưới đây minh họa không cần thiết cho một số loại đặc điểm vì có thể quá tải bằng cách sử dụng các bộ định tính. – Corristo

Trả lời

12

Bạn có thể có bộ kiểm tra lại về chức năng thành viên. Sao chép ví dụ từ 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" 
} 

Vì vậy, trong tình hình của bạn, bạn sẽ muốn có một cái gì đó như thế này

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &; 
Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &&; 
+0

Có, thực sự, nhưng tuy nhiên các vòng loại ref là những gì tôi cần. – Corristo

4

Bạn có thể sử dụng vòng loại tham chiếu đến quá tải chức năng thành viên tương tự như cách bạn muốn sử dụng const để quá tải cho const và không phải const đối tượng:

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) const& 
{ 
    // implementation if this is not a temporary 
} 

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) && 
{ 
    // implementation if this IS a temporary 
} 
2

Có. Nếu bạn triển khai hai phương pháp sau:

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &; 
Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &&; 

thứ hai sẽ được gọi nếu *this là giá trị.

Các vấn đề liên quan