2013-02-19 12 views
5
class Interface 
{ 
}; 

class Class : public Interface 
{ 
}; 

class Foo 
{ 
public: 
    std::vector<std::shared_ptr<Interface>>& GetInterfaces() 
    { 
     return *(std::vector<std::shared_ptr<Interface>>*)(&m_data); 
     //return m_data; 
    } 

private: 
    std::vector<std::shared_ptr<Class>> m_data; 
}; 

Questo funziona ma è brutto e spaventoso. Esiste un modo migliore/più sicuro per farlo? Non voglio fare m_data di tipo std::vector<std::shared_ptr<Interface>> perché il modulo Foo appartiene funziona interamente con Class 's, Interface (e Foo::GetInterfaces()) sono implementati per interagire con un modulo separato che dovrebbe sapere solo la funzionalità Interface.Come trasmettere un vettore di shared_ptrs di una classe derivata a un vettore di share_ptrs di una classe base

Fammi sapere se qualcosa qui non è chiaro, ha senso per me, ma ho battuto la testa contro il problema per un po '.

risposta

7

La trasmissione non è corretta, sono tipi distinti; Sono abbastanza certo che stai invocando un comportamento indefinito.

È necessario costruire un nuovo vettore e restituirlo per valore.

std::vector<std::shared_ptr<Interface>> b (m_data.begin(), m_data.end()); 
return b; 

Questo dovrebbe essere ancora abbastanza economico (1 assegnazione).

+0

Qual è il puntatore condiviso intenzione di fare in quella situazione? Non sono sicuro che vorrà condividere i puntatori tra due diversi tipi di puntatore condiviso! –

+0

@MichaelKohne no questo va bene. – 111111

+0

Ah, sposta la semantica per la vittoria! dovrebbe rendere il ritorno di valore ok. –

4

Oltre a ciò non è possibile con l'implementazione di vector, il problema è anche che i riferimenti non vengono convertiti. Il tuo codice è anche peggio e il comportamento non è definito.

Quello che puoi fare è fornire un'interfaccia che espone un intervallo o begin/end invece del contenitore stesso. Se lo combini con un transform_iterator che esegue la conversione, dovresti essere impostato.

codice di esempio:

class Interface { 
    virtual ~Interface(); 
}; 

class X : public Interface {}; 

class C { 

private: 
    typedef std::shared_ptr<Interface> iptr_type; 
    typedef std::shared_ptr<Class> ptr_type; 
    std::vector<ptr_type> v_; 

    struct F { 
    iptr_type 
    operator()(ptr_type p) { return iptr_type(p); } 
    }; 

    typedef boost::transform_iterator< 
    F, std::vector<ptr_type>::iterator> iiterator; 

public: 
    iiterator 
    begin() 
    { 
    return boost::make_transform_iterator(
     begin(v_), F()); 
    } 

    iiterator 
    end() 
    { 
    return boost::make_transform_iterator(
     end(v_), F()); 
    } 
}; 
+0

Se ha senso nel tuo caso d'uso esponendo un' .begin() 'e l'interfaccia iteratore' .end() 'è una buona opzione. – 111111

+0

@ 111111 Certo, anche quello. Ma immagino che le gamme siano la cosa più alla moda. – pmr

+0

il mio commento è stato uno a sostegno della tua idea :) – 111111

Problemi correlati