2016-06-08 23 views
5

Ich implementiere ein Decorator-Muster auf unveränderlichen Objekten mit dem Pointer-zu-Implementierungs-Idiom. Im Grunde genommen mein Setup sieht wie folgt ausIst es möglich, zu erkennen, ob das Objekt innerhalb der Elementfunktion temporär ist?

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

Hier wird die decorateWith Funktion soll ein anderes Verhalten haben, je nachdem, ob das Objekt wird callen auf eine temporäre oder nicht. Wenn es für ein nicht-temporäres Objekt aufgerufen wird, soll es eine neue Objektinstanz zurückgeben, wo ich eine tiefe Kopie des aktuellen Objekts erstellen und es in dem unique_ptr des Dekorators während des Impl-Zeigers des neuen Objekts selbst speichern muss zeigt auf den Dekorateur. Wenn jedoch decorateWith für eine temporäre aufgerufen wird, genügt es, einen ObjectDecorator zu erstellen und den impl-Zeiger des aktuellen Objekts einfach in den impl-Zeiger des Dekorators zu bewegen und das Objekt auf den neuen Decorator zu zeigen.

Um zu erreichen, dass ich eine Möglichkeit, aus dem Aufruf von decorateWith zu ermitteln, ob das Objekt ein temporäres oder nicht ist, und verwenden Sie dann Tag-Dispatch basierend auf das Ergebnis dieser Prüfung. Ist das möglich?

Beste Xodion

EDIT: Beispiel Anrufer Code könnte wie folgt aussehen:

  • decorateWith auf einer nicht nur vorübergehenden genannt wird

    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 auf Zeit genannt wird,

    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

Ihre Erklärung könnte besser mit Beispielaufrufcode gesichert werden. – kfsone

+2

Fragen Sie, ob das 'Objekt' 'decorateWith' aufgerufen wird von ist temporär, oder ob das Argument zu' decorateWith' temporär ist? – md5i

+0

Ich möchte mich nur bedingt bewegen, wenn das Objekt, auf dem decorateWith aufgerufen wird, ein temporäres Objekt ist und ansonsten eine tiefe Kopie erstellt. Es geht also darum, zu prüfen, ob ein Objekt temporär ist. Wie die untenstehenden Antworten zeigen, ist keine Art von Typeigenschaft erforderlich, da man ref-Qualifikatoren überladen kann. – Corristo

Antwort

12

Sie können Ref-Qualifier für Elementfunktionen verwenden. Kopierte Beispiel von 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" 
} 

So in Ihrer Situation, würden Sie so etwas wie dieses

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

Ja, in der Tat, aber trotzdem sind die Ref-Qualifiers das, was ich brauche. – Corristo

4

Sie Referenz-Qualifikation nutzen können, um eine Überlastung der Member-Funktion ähnlich wie haben wollen Sie const verwenden würde, um eine Überlastung für const und nicht const Objekte:

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

Ja. Wenn Sie die folgenden zwei Methoden implementieren:

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

wird die zweite aufgerufen werden, wenn *this ein R-Wert ist.