2016-06-08 40 views
5

Wdrażam wzór dekoratora na niezmiennych obiektach z idiomem do implementacji. Zasadniczo moja konfiguracja wygląda następującoCzy można wykryć, czy obiekt jest tymczasowy z funkcji członka?

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

Tutaj funkcja decorateWith ma mieć różne zachowania w zależności od tego, czy obiekt jest Callen na to tymczasowa, czy nie. Jeśli wywoływany jest obiekt nie tymczasowy, powinien zwrócić nową instancję obiektu, w której mam wykonać głęboką kopię bieżącego obiektu i zapisać go w unique_ptr of decorator, podczas gdy wskaźnik impl nowego obiektu sam w sobie wskazuje na dekoratora. Jeśli jednak decorateWith jest wywoływana tymczasowo, wystarczy utworzyć ObjectDecorator i po prostu przenieść wskaźnik impl-in bieżącego obiektu do wskaźnika impl po stronie dekoratora i pozwolić obiektowi wskazać nowy dekorator.

W celu uzyskania impelencji potrzebuję sposobu na ustalenie z poziomu zaproszenia do dekoracji. Z tym, czy obiekt jest tymczasowy, czy nie, a następnie użyj wysyłki znacznika na podstawie wyniku tego sprawdzenia. Czy to jest możliwe?

Najlepszy Xodion

EDIT: Przykładowy kod rozmówca mógłby wyglądać następująco:

  • decorateWith nazywa mieć charakteru tymczasowego

    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 nazywa się na tymczasowe

    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

Twoje wyjaśnienie może być lepiej zabezpieczone przykładowym kodem telefonicznym. – kfsone

+2

Czy chcesz zapytać, czy wywołanie 'Object'' decorateWith' jest tymczasowe, czy argument "decorateWith" jest tymczasowy? – md5i

+0

Chcę warunkowo przenieść tylko wtedy, gdy obiekt, na którym jest wywoływany jest wywoływany, jest tymczasowy i wykonać w zamian kopię głęboką, więc chodzi o to, jak sprawdzić, czy obiekt jest tymczasowy. Jak ilustrują poniższe odpowiedzi, nie ma potrzeby stosowania jakiejś cechy typu, ponieważ można przeciążać za pomocą refreferencji. – Corristo

Odpowiedz

12

Możesz mieć kwalifikatory ref w funkcjach składowych. Kopiowane przykład z 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" 
} 

to w danej sytuacji, co chcesz mieć coś takiego

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

Tak, rzeczywiście, ale mimo to kwalifikatory są tym, czego potrzebuję. – Corristo

4

Można wykorzystać kwalifikatorów odniesienia do przeciążenia funkcji członka podobny sposób chcesz wykorzystać const przeciążyć dla const i nie- const obiektów:

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

Tak. W przypadku zastosowania dwóch następujących metod:

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

drugi zostanie wywołana jeżeli *this jest rvalue.