2017-06-08 4 views
0

Ich habe eine Manager-Klasse, die Clients Komponenten über zwei Methoden hinzufügen können: eine ohne Argument, die die Komponente standardmäßig erstellen und eine andere, die einen Rvalue (der Client eine benutzerdefinierte verwenden soll) Konstruktor der Komponente).Verhindern Kopie-Erstellung mit make_shared

Hier ist der Code, den ich mit aufkommen:

template <class TComponent> 
std::shared_ptr<TComponent> AddComponent() 
{ 
    return AddComponent(TComponent{ this }); 
} 

template <class TComponent> 
std::shared_ptr<TComponent> AddComponent(const TComponent &&obj) 
{ 
    auto ptr = std::make_shared<TComponent>(obj); 
    vec.push_back(ptr); 
    return ptr; 
} 

Das Problem, das ich habe ist, dass std :: make_shared immer das Objekt kopieren-Konstrukte. Gibt es eine Möglichkeit, dieses Verhalten zu verhindern? Ich lese über perfekte Weiterleitung aber es scheint hier nicht zu helfen.

Antwort

2

Ich lese über perfekte Weiterleitung, aber es scheint hier nicht zu helfen.

Ich sehe nicht, warum es nicht würde.

Entfernen Sie einfach die const bewegen Konstruktion möglich zu machen, und fügen Sie std::forward:

template <class TComponent> 
std::shared_ptr<TComponent> AddComponent(TComponent &&obj) 
{ 
    auto ptr = std::make_shared<TComponent>(std::forward<TComponent>(obj)); 
    vec.push_back(ptr); 
    return ptr; 
} 

Nun wird rvalues ​​bewegt werden. Lvalues ​​werden kopiert, die Sie nicht vermeiden können.

+0

In Ordnung, das habe ich versucht, perfekte Weiterleitung anzuwenden. Also irre ich mich, wenn ich denke, dass 'TestComponent {& manager, 0.5f}' in 'manager.AddComponent (TestComponent {& manager, 0.5f})' ein rvalue ist? Mit dieser Zeile und dem Code in Ihrem Beitrag oben wird der Kopierkonstruktor immer noch von make_shared aufgerufen. – Aer

+1

@Aer ja, das ist ein rvalue. Der Kopierkonstruktor würde aufgerufen werden, falls die Klasse TestComponent nicht beweglich ist. Hast du das überprüft? In jedem Fall empfehle ich, ein [mcve] zu erstellen. – user2079303

+0

Sie haben Recht! Das Problem war in meinem Beispiel: Ich hatte einen Kopierkonstruktor und keinen Move-Konstruktor implementiert. Das Nachschlagen der Regeln von move-constructor generation hat mich daran erinnert, dass der Compiler es nur erzeugte, wenn es keinen von Benutzern deklarierten Kopierkonstruktor gab. Ein bisschen dumm von meiner Seite! Danke für Ihre Hilfe. – Aer

Verwandte Themen