2016-07-31 14 views
1

Das Folgende ist ein Versuch, einen gemeinsamen Zeiger mit einer modifizierten Semantik von operator== Umsetzung:Wie wird in privat abgeleitete Kindtypen umgewandelt?

template <typename T> 
struct deref_shared_ptr: private std::shared_ptr<T> { 
    using Base = std::shared_ptr<T>; 
    // ... using statements to include functionality from the base. 

    bool operator==(const deref_shared_ptr rhs) const { 
     return (**this == *rhs); 
    } 
}; 

ich mit der Umsetzung eines Äquivalents std::make_shared für diese Art bin zu kämpfen. Dies ist mein Versuch:

template< class T, class... Args > 
deref_shared_ptr<T> make_deref_shared(Args&&... args) { 
    return reinterpret_cast<deref_shared_ptr<T>>(std::make_shared<T>(args...)); 
} 

Das funktioniert nicht: die Compiler (g++ 5.4.0) beschwert mich über eine ungültige Stimme. Warum funktioniert es nicht und was sollte ich anstelle dieser Besetzung tun?

+0

Verwenden 'friend'. Es ist keine Sünde. –

+0

@ n.m. Meinst du einen privaten Konstruktor zu haben, der ein 'std :: shared_ptr'-Argument annimmt? – AlwaysLearning

+0

Sorry, habe deinen Code nicht zu genau angeschaut. Das Umwandeln in einen abgeleiteten Typ (kein Zeiger) ist nur möglich, wenn der abgeleitete Typ einen Konstruktor hat, der den übergeordneten Typ annimmt, oder der übergeordnete Typ einen Konvertierungsoperator vom richtigen Typ hat. Also ja, du brauchst einen Konstruktor. Ob Sie es privat machen oder nicht, liegt an Ihnen, –

Antwort

3

Sie sehen diese Compiler-Fehlermeldung, da die reinterpret_cast nicht Abgüsse durch die private Erbschaft machen kann. Bitte überprüfen Sie die folgenden Themen zu diesem Thema: difference between c++ casts, conversion which may be handled by c-style cast only.

Der einzige Weg, durch die private Erbe zu gehen, ist die c-Casts. So, Ihr Beispiel ändern, wie macht die Arbeit Ihres Beispiel folgt:

template< class T, class... Args > 
deref_shared_ptr<T> make_deref_shared(Args&&... args) { 
    return (deref_shared_ptr<T>)(std::make_shared<T>(args...)); 
} 

Der c-Casts ist im allgemeinen Fall nicht sicher, da es in Fällen von Mehrfachvererbung und einigen anderen Fällen funktioniert nicht richtig, aber AFAIK ist es sicher in diesem Fall.

+0

Wäre die Antwort in diesem Fall umgekehrt (d. H. Von Kind zu Basis)? Ich denke, dass ich diesen Cast für die Implementierung von Konstruktoren des neuen Typs benötigen werde. – AlwaysLearning

+0

Ja, sollte es sein. C++ - Umwandlungen haben keine Informationen über private Vererbung – alexeykuzmin0

+0

Die Lösung funktioniert nicht. Der Compiler beklagt sich über das Fehlen eines Konstruktors, der ein Argument std :: shared_ptr akzeptiert, das ich offensichtlich nicht bereitstellen möchte. – AlwaysLearning

0

Ich schlage vor, deref_shared_ptr einen Konstruktor zu implementieren, der einen std::shared_ptr als Parameter erhält, so dass die Konvertierung möglich wäre. Gerade jetzt Ihr Compiler hat keine Ahnung, wie ein deref_shared_ptr von einem std::shared_ptr zu machen. Genau dies werden wir Ihrem Compiler beibringen.

Ich bemerkte, dass Sie eine benutzerdefinierte operator== hinzufügen, um Ihren Typ mit einer std::shared_ptr korrekt zu vergleichen. Hier wollen wir dasselbe machen, aber mit Konstruktor. Wir wollen einen Konstruktor, der korrekt mit Ihrem Typ mit einem std::shared_ptr Konstruieren!

Der Konstruktor würde wie folgt aussehen:

template<typename T> 
struct deref_shared_ptr : private std::shared_ptr<T> { 
    // An alias to the parent may help msvc with templated parent types 
    using parent = std::shared_ptr<T>; 

    // Implement a constructor that takes shared_ptr by copy and move 
    deref_shared_ptr(const parent& ptr) : parent{ptr} {} 
    deref_shared_ptr(parent&& ptr) : parent{std::move(ptr)} {} 

    // stuff... 
}; 

Dann wird die Schliesser trivial zu implementieren:

template<typename T, typename... Args> 
deref_shared_ptr<T> make_deref_shared(Args&&... args) { 
    // Don't forget perfect forwarding here! 
    return std::make_shared<T>(std::forward<Args>(args)...); 
} 

EDIT:

Alternativ, wenn Ihre Konstrukteure sind nicht tut eine Operation, können Sie nutzen vererben Bauer machen:

Das würde Konstruktorimplementierungen vereinfachen und Ihren Typ durch Konstruktion mit std::shared_ptr kompatibel machen.

Verwandte Themen