Penso ai concetti come a una sorta di meta-interfaccia. Classificano i tipi dopo le loro abilità. La prossima versione di C++ fornisce concetti nativi. Non l'avevo capito fino a quando non mi sono imbattuto in concetti di C++ 1x e in che modo hanno permesso di mettere insieme tipi diversi ma non correlati. Immagina di avere un'interfaccia Range
. Puoi modellarlo in due modi. Uno è un rapporto sottotipo:
class Range {
virtual Iterator * begin() = 0;
virtual Iterator * end() = 0;
virtual size_t size() = 0;
};
Naturalmente, ogni classe che deriva da che implementa l'interfaccia Range e può essere utilizzato con le funzioni. Ma ora vedi che è limitato. Che dire di un array? È anche una gamma!
T t[N];
begin() => t
end() => t + size()
size() => N
Purtroppo non è possibile ricavare una matrice dalla classe Range che implementa tale interfaccia.È necessario un metodo aggiuntivo (sovraccarico). E i contenitori di terze parti? Un utente della tua libreria potrebbe voler utilizzare i suoi contenitori insieme alle tue funzioni. Ma non può cambiare la definizione dei loro contenitori. Qui, i concetti entrano in gioco:
auto concept Range<typename T> {
typename iterator;
iterator T::begin();
iterator T::end();
size_t T::size();
}
Ora, dire qualcosa sulle operazioni supportate di un certo tipo che possono essere soddisfatte se T
ha le funzioni membro appropriate. Nella tua libreria, scriverebbe la funzione generica. Questo ti permette di accettare qualsiasi tipo purché supporta le operazioni necessarie:
template<Range R>
void assign(R const& r) {
... iterate from r.begin() to r.end().
}
E 'una sorta di grande sostituibilità. Qualsiasi tipo si adatta al disegno di legge che aderisce al concetto e non solo a quei tipi che implementano attivamente un'interfaccia. Il prossimo standard C++ va oltre: definisce un concetto di Container
che può essere adattato da array semplici (da qualcosa che si trova mappa concettuale che definisce come alcuni tipi si adattano ad alcuni concetti) e altri, contenitori standard esistenti.
Il motivo per cui viene presentato è perché ho un contenitore basato su modelli, in cui i contenitori stessi hanno una relazione gerarchica. Mi piacerebbe scrivere algoritmi che usano questi contenitori senza preoccuparsi di quale contenitore specifico sia. Inoltre, alcuni algoritmi trarrebbero vantaggio dal sapere che il tipo di modello soddisfaceva determinati concetti (confrontabile, ad esempio).
Si può effettivamente fare entrambi con i modelli. È possibile mantenere la relazione gerarchica per condividere il codice e quindi scrivere gli algoritmi in modo generico. Ad esempio, per comunicare che il tuo contenitore è paragonabile. E 'come standard di accesso casuale/avanti/uscita/ingresso categorie di iteratori sono implementate:
// tag types for the comparator cagetory
struct not_comparable { };
struct basic_comparable : not_comparable { };
template<typename T>
class MyVector : public BasicContainer<T> {
typedef basic_comparable comparator_kind;
};
/* Container concept */
T::comparator_kind: comparator category
E' un modo semplice ragionevole per farlo, in realtà. Ora puoi chiamare una funzione e inoltrerà alla corretta implementazione.
template<typename Container>
void takesAdvantage(Container const& c) {
takesAdvantageOfCompare(c, typename Container::comparator_kind());
}
// implementation for basic_comparable containers
template<typename Container>
void takesAdvantage(Container const& c, basic_comparable) {
...
}
// implementation for not_comparable containers
template<typename Container>
void takesAdvantage(Container const& c, not_comparable) {
...
}
Ci sono in realtà diverse tecniche che possono essere utilizzate per implementarlo. Un altro modo è utilizzare boost::enable_if
per abilitare o disabilitare le diverse implementazioni ogni volta.
C++ 1x? Significa che hanno rinunciato a rilasciare il nuovo standard in questo decennio o stai parlando del futuro sviluppo del C++? – jpalecek
http://www.research.att.com/~bs/C++0xFAQ.html#concepts – jmucchiello
jpalecek, vogliono rilasciarlo nel 2010. Ho l'abitudine di chiamarlo C++ 1x :) –