2015-04-26 17 views
6

Sto per progettare un'API in cui esistono due classi: una classe data/di calcolo e un contenitore per questa classe. Il container, tuttavia, non è semplicemente un contenitore stupido, ma porta anche informazioni sulla collezione nel suo complesso che va oltre le solite cose che possono essere implementate con gli iteratori.Funzioni di Accessor per contenitori con std :: unique_ptr

Così, il contenitore avvolge fondamentalmente un std::vector, aggiunge alcuni attributi precalcolate, funzioni di utilità, ecc Che le API della classe contenitore dovrebbe anche contenere è

  1. Un metodo per aggiungere le istanze dei dati/calc classe,
  2. metodi di accesso.

non mi vogliono semplicemente aprire la std::vector al pubblico, perché l'aggiunta di una nuova classe di dati/calc al contenitore fa sì che il ri-calcolo di una serie di attributi della classe collezione. Tuttavia, desidero fornire un metodo accessor uguale ai metodi accessor del contenitore STL at() e operator [].

Inizialmente, ho aggiunto un attributo privato del tipo std::vector<std::unique_ptr<DataClass>>. Esiste un metodo addDataObject(DataObject *d) che racchiude l'oggetto in un unique_ptr e aggiorna le statistiche.

Il problema, tuttavia, viene fornito con i metodi di accesso: Quale sarebbe il loro tipo di ritorno?

  • Semplicemente tornando std::unique_ptr<DataClass> & non sembra essere un progetto API pulito: l'utente delle API non ha bisogno di sapere che uso puntatori intelligenti. (Vedi anche la presentazione di Herb Sutter su C++ 11)
  • Tornando DataClass *& non è possibile, soprattutto non per operator [], perché posso accedere solo il puntatore grezza di un std::unique_ptr usando il metodo del puntatore intelligente get(), il che non mi dà un riferimento.
  • Il ritorno di DataClass & non sembra avere senso, soprattutto quando sto memorizzando i puntatori (allocazione heap vs. stack).
  • Il ripristino di DataClass * viola il principio di minima sorpresa, perché se un metodo è denominato nel senso dei metodi accessor del contenitore STL, ci si aspetterebbe che restituisca un riferimento, in particolare per operator [].

titolo di esempio, questo sarebbe un esempio semplificato:

class DataClass 
{ 
    Container *m_parent; 
    /* ... other member attributes/parameters ... */ 
public: 

    /* A method that calculates something based on the attributes: */ 
    double someComplicatedCalculation(const double &input); 
}; 


class Container 
{ 
    std::vector<std::unique_ptr<DataClass>> m_collection; 

    /* more attributes: maintenance info, precomputed values, etc. */ 

    public: 

     void addDataObject(DataClass *d); 

     /* What would the right return type be? */ 

     DataClass *&at(const int &index); 
     const DataClass *&at(const int &index) const; 
     DataClass *&operator [](const int &index); 
     const DataClass *&operator [](const int &index) const; 
}; 
+0

Qual è il significato di unique_ptr in questo contesto? Vuoi che venga invalidato quando viene chiamato? Vuoi che esistano due copie di unique_ptr? Quindi non è molto unico. –

+1

C'è un motivo per cui i puntatori del negozio nel tuo vettore piuttosto che gli oggetti stessi? – Galik

+0

@Galik OP ottiene gli oggetti con il puntatore e assume la proprietà - perché copiare o spostare un oggetto quando è sufficiente copiare il puntatore? – Barry

risposta

1

sua sempre difficile quando non si conosce tutti i dettagli, ma qui è quello che penso:

  • Semplicemente restituire std::unique_ptr<DataClass> & non sembra essere un design API pulito: l'utente dell'API non ha bisogno di sapere che io uso sm puntatori di arte. (Vedi anche la presentazione di Herb Sutter su C++ 11)

Sicuramente sì.

  • Tornando DataClass *& non è possibile, soprattutto non per operator [], perché posso accedere solo il puntatore non elaborato di un std::unique_ptr utilizzando il metodo del puntatore intelligente get(), che fa non mi dare un riferimento.

Infatti.

  • Tornando DataClass & non sembra avere senso, specialmente quando sto memorizzare i puntatori (mucchio vs. allocazione dello stack).

Questo ha senso. Quello che penso possa non avere senso è archiviare i puntatori per cominciare. A std::vector memorizza tutto sullo heap comunque, quindi se questo è il motivo per usare i puntatori, non si applica.

  • Tornando DataClass * violerebbe la princpile di minima sorpresa, perché se un metodo viene chiamato nel senso dei STL metodi contenitore accessor, ci si aspetterebbe che per restituire un riferimento, soprattutto per operator [].

Infatti.

Direi che dovresti restituire DataClass&. Probabilmente non si dovrebbe usare puntatori nella vostra std::vector ma se necessario usarle è possibile effettuare le funzioni di accesso come:

DataClass& operator[](std::size_t index) 
{ 
    return *m_collection[index]; 
} 

Ma meglio sarebbe non usare puntatori:

class Container 
{ 
    std::vector<DataClass> m_collection; 

    DataClass& operator[](std::size_t index) 
    { 
     return m_collection[index]; 
    } 

    // ... 
}; 
+0

'Ti dà il puntatore e puoi restituire un riferimento a quello. Cosa? – Yakk

+0

@Yakk È possibile restituire i riferimenti ai puntatori ma l'OP sembra ritenere che non sia possibile: "Returning DataClass * & non è possibile" – Galik

+0

@Galik Si restituirà un riferimento a un puntatore temporaneo. Quale sarebbe il punto di ciò? – Barry

2

Restituzione DataClass & non sembra avere senso, specialmente quando sto memorizzando i puntatori (allocazione heap vs. stack).

Non sono d'accordo. Questo è ciò che restituiscono tutti i contenitori standard. A meno che il fatto che tu stia usando unique_ptr è qualcosa che dovrebbe essere visibile agli utenti (e presumo che non dovrebbe essere), allora il percorso di sorpresa minima sarebbe semplicemente fare come fa la libreria standard: restituire un lvalue riferimento all'oggetto.

Inoltre, restituire un riferimento rende evidente la proprietà. Se dovessi restituire un puntatore, dovresti indicare da qualche parte che l'utente non deve cancellarlo.

+0

Grazie per il suggerimento con la proprietà. Vorrei poter accettare due risposte ... – Technaton

Problemi correlati