2016-10-28 6 views
0

Ich implementiere einen benutzerdefinierten Vektor von Zeigern my_ptr_vector.Container kovariant machen

Ich habe eine Klasse Base und eine Derived Ableiten Base.

Ich habe eine Methode, die sowohl auf my_ptr_vector<Base> als auch auf my_ptr_vector<Derived> (durch const Referenz!) Handeln sollte. Es ruft natürlich nur die Elemente der Klasse Base auf.

Der Compiler beklagt sich jedoch, es habe keine Möglichkeit my_ptr_vector<Derived> in my_ptr_vector<Base> zu konvertieren.

Minimal Beispiel die Wiedergabe der Ausgabe:

#include <vector> 
#include <memory> 

class Base {}; 
class Derived : public Base {}; 

template<typename Element> 
class my_ptr_vector : public std::vector< std::unique_ptr<Element> > {}; 

void funct(const my_ptr_vector<Base>& vect) {} 

int main() 
{ 
    my_ptr_vector<Derived> vect; 
    funct(vect); 
} 

Fehler:

no suitable user-defined conversion from "my_ptr_vector<Derived>" to "const my_ptr_vector<Base>" exists 

ich gefunden habe here, dass ich es, wenn ich von einem my_ptr_vector<U> einen Konstruktor und Zuweisungsoperator bereitgestellt machen könnte funktionieren, mit U generisch, so dass U* in T* umgewandelt werden kann.

der Tat, wenn in dem Beispiel, das ich die Klasse dies zu ändern, funktioniert es

template<typename Element> 
class my_ptr_vector : public std::vector< std::shared_ptr<Element> > { 
public: 
    my_ptr_vector() {} 

    ///copy constructor from vector of pointers to generic U 
template<typename DerivedElement> 
    my_ptr_vector(const my_ptr_vector<DerivedElement>& oth) 
    { 
     printf("Oh, noes!"); //we don't want this method executed! 

     resize(oth.size()); 

     for (std::shared_ptr<Element> ptr : oth) 
     { 
      push_back(ptr); 
     } 
    } 
}; 

Aber es hat die print Anweisung im Konstruktor ausführen-es nicht nur ein Hinweis ist, dass es keine Sorgen sollte ; es führt tatsächlich die Umwandlung durch!

Gibt es eine Möglichkeit, dies zu vermeiden?

Eine andere mögliche Lösung ist natürlich func Templat zu machen:

template<typename T> 
    void funct(const my_ptr_vector<T>& vect) {} 

jedoch auf diese Weise ich die Informationen verlieren, dass im Inneren func, Base die Elemente vect sind immer vom Typ.

+2

Es ist einfacher, wenn Sie uns Code zeigen ([mcve]). Mein erster Gedanke ist es, 'my_ptr_vector ' zu verwenden, was der übliche Weg ist, Vektoren von Klassen zu behandeln, von denen einige abgeleitet werden können. –

+0

vielleicht suchen Sie nach einem guten alten [std :: vector] (http://en.cppreference.com/w/cpp/container/vector) von [std :: unique_ptr] (http: //en.cppreference. com/w/cpp/Speicher/unique_ptr) oder [std :: shared_ptr] (http://en.cppreference.com/w/cpp/memory/shared_ptr)? –

+0

@TopologicalSort du hast Recht, fertig :) –

Antwort

0

Dies scheint zu tun, was Sie wollen. Der zweite Teil des Codes, der copy ctor, musste nicht geändert werden.

Ich glaube nicht, dass Sie davon wegkommen müssen, zu std::unique_ptr zu werfen. Es will, dass selbst wenn es eine Base* schiebt.

#include <vector> 
#include <memory> 

class Base {}; 
class Derived : public Base {}; 

template<typename Element> 
class my_ptr_vector : public std::vector< std::unique_ptr<Element> > {}; 

void funct(const my_ptr_vector<Base>& vect) {} 

int main() 
{ 
    my_ptr_vector<Base> vect; 
    vect.push_back(std::unique_ptr<Base>(new Derived)); 

    funct(vect); 
} 
+0

Ja das kompiliert; aber ich würde die Möglichkeit verlieren, Nur-Abgeleitete-Methoden aufzurufen, und das brauche ich. –

+0

@FrancescoDondi nein würdest du nicht - das ist, was 'dynamic_cast' /' static_cast' gemacht wurde für ... –

+0

Mhh ja du hast Recht, aber es ist hässlich. Anstatt sich innerhalb 'func' zu erinnern, dass der Typ' Base' und nicht 'T' ist, muss ich mich draußen daran erinnern, dass der Typ' Abgeleitet' ist, nicht 'Basis' ... was ich will ist, den Typ zu verschieben- Überprüfung auf den Compiler. –

Verwandte Themen