2010-10-18 12 views
9

Il C++ STL non sembra utilizzare molto spesso le classi base puramente astratte (anche le interfacce). So che molte cose possono essere raggiunte con gli algoritmi STL o con la metaprogrammazione di template intelligente.Perché non c'è un'interfaccia "Iterable" nell'STL?

Tuttavia, per alcuni casi d'uso (ad esempio, in un'API, se non voglio essere specifico sul tipo di contenitore che ottengo, solo sugli elementi che contiene), un'interfaccia del seguente modulo sarebbe bello:

template<typename T> struct forward_iterable { 
    struct iterator { 
     typedef T value_type; 
     typedef T& reference; 
     typedef T* pointer; 
     virtual reference operator*() const = 0; 
     virtual pointer operator->() const = 0; 
     virtual bool operator==(const iterator&) const = 0; 
     virtual bool operator!=(const iterator&) const = 0; 
     virtual operator const_iterator() const = 0; 
     virtual iterator& operator++() = 0; 
     virtual iterator operator++(int) = 0; 
    }; 
    struct const_iterator { ... }; // similar, but with const references 

    virtual iterator begin() = 0; 
    virtual const_iterator begin() const = 0; 
    virtual iterator end() = 0; 
    virtual const_iterator end() const = 0; 
}; 

Se i contenitori STL implementano questa classe come la funzione non virtuale, questo sarebbe, a mio parere, non influisce sulle prestazioni (se uso i contenitori direttamente e non tramite questa interfaccia). Quindi, perché ci sono così poche "interfacce" nell'STL? O sto pensando troppo ai termini "Java"?

+0

Hmm, ho appena pensato ad una complicazione: a causa della natura generica degli operatori di confronto, sarebbe necessario un controllo dinamico del tipo per garantire che gli iteratori siano "compatibili". È questa la ragione per cui non funziona? – summentier

risposta

6

STL (che è un sottoinsieme della libreria standard) non utilizza affatto OOP (come nel polimorfismo di runtime) ed è di progettazione.

Con la progettazione, non ci sarebbero problemi nel restituire gli iteratori in base al valore (la covarianza non funziona per i tipi di valore)? Cioè, non sarebbe inevitabile che l'intera cosa dovesse fare affidamento su membri statici (che puoi restituire per riferimento) o su iteratori allocati su heap? Quest'ultimo sembrerebbe piuttosto scomodo in un linguaggio non raccolto dalla spazzatura.

cosa si sta descrivendo (un iteratore su modelli sul tipo di valore) può essere realizzato utilizzando una tecnica chiamata di tipo cancellazione (e si può trovare any_iterator implementazioni là fuori), proprio come function e any tipi di boost.

L'idea di base è:?

//less templated interface 
template <class T> 
class any_iterator_base 
{ 
    virtual void increment() = 0; 
    /*...*/ 
}; 

//derived class templated on iterator type 
template <class Iter, class T> 
class any_iterator_impl: public any_iterator_base<T> 
{ 
    Iter it; 
    virtual void increment() { ++it; } 
    /*...*/ 
}; 

//and a class for the user which makes it all act like a regular value type 
template <class T> 
class any_iterator 
{ 
    shared_ptr<any_iterator_base<T> > it; 
public: 
    template <class Iter> 
    any_iterator(Iter iterator): it(new any_iterator_impl<Iter, T>(iterator)) {} 
    any_iterator& operator++() { it->increment(); return *this; } 
    //... 
}; 

int main() 
{ 
     std::vector<int> vec; 
     any_iterator<int> it = vec.begin(); 
     //... 
} 

può essere più complicato di quello (ad esempio, hanno bisogno di fare qualcosa per descrivere e far rispettare categoria iteratore ?, come sarebbe il confronto di due any_iterators lavoro (doppia spedizione/RTTI)).

2

La ragione per cui non si vedono molte classi di base astratte in stile "interfaccia" nell'STL è perché si basa molto sui modelli C++. Quando si usano i modelli C++, praticamente qualsiasi classe qualunque, qualunque sia la sua parentela, farà tutto il tempo in cui supporta tutti i metodi che il modello prova ad usare.

C'è una sorta di interfaccia implicita, ma in realtà la scrittura non è attendibile. Nella mia codifica tendo a scriverne uno in ogni caso, proprio come una comodità per l'utente, ma non è così che i redattori di STL rotolano.

0

Le strutture STL non sono definite tenendo in considerazione l'ereditarietà. Non è facile fare un buon esempio per la sottoclasse di qualsiasi delle collezioni di stl. tenendo a mente ciò, la stl non ti fa 'pagare' alcun costo che potrebbe essere stato associato alla normale ereditarietà di classe. Se si dovessero utilizzare metodi virtuali, non potrebbero essere indicati dall'ottimizzatore.

Inoltre, STL vuole essere compatibile con cose che non potrebbero possibilmente ereditare da una classe di base astratta di livello superiore, come gli array.

+0

Penso che le specializzazioni non virtuali dei metodi virtuali possano essere effettivamente sottolineate se il metodo della sottoclasse viene chiamato direttamente (e non tramite la classe base), quindi l'aggiunta di interfacce aggiungerebbe solo penalità prestazionali laddove necessario. – summentier

Problemi correlati