Operatore Typedef e ostream per un std::vettore
Domanda
Ho creato una classe Chromosome che alla fine è diventata semplicemente un wrapper per vector con un operatore ostream, quindi ho deciso di digitare invece def vector.Tuttavia, ho problemi con l'operatore ostream basato su modello...È questo il modo migliore per farlo?(Ho visto alcuni approcci e non sono riuscito a farne funzionare nessuno)
template<typename G>
class Chromosome {
public:
typedef typename std::vector<G> type;
typedef typename std::pair<type *,type *> ptr_pair;
};
template<typename G> //line 19 below:
std::ostream& operator<<(std::ostream& os, const Chromosome<G>::type& chromosome) {
for(auto iter = chromosome.begin(); iter != chromosome.end(); ++iter)
std::cout << *iter;
return os;
}
Al momento l'errore che ricevo è:
chromosome.h:19: error: expected unqualified-id before ‘&’ token
chromosome.h:19: error: expected ‘)’ before ‘&’ token
chromosome.h:19: error: expected initializer before ‘&’ token
Saluti.
Soluzione
Sfortunatamente, non esiste un modo pulito per farlo perché il compilatore non può dedurre il tipo di G
dalla dichiarazione della funzione
template<typename G>
std::ostream& operator<<(std::ostream& os, const typename Chromosome<G>::type& chromosome);
Il motivo è che se dovessi specializzarti Chromosome
per tipi diversi, potresti ritrovarti in una situazione in cui il compilatore non è in grado di dedurre in modo inequivocabile G
.Per esempio:
template <typename G> class Chromosome {
public:
typedef std::vector<G> type; // No typename needed here, BTW
};
template <> class Chromosome<int> {
public:
typedef std::vector<double> type;
};
Ora, cosa accadrebbe se facessi questo?
vector<double> v;
cout << v << endl;
Il compilatore non può dire se G
È double
O int
in questo caso, perché entrambi Chromosome<int>
E Chromosome<double>
Avere vector<double>
come tipo nidificato.
Per risolvere questo problema, dovrai utilizzare esplicitamente il tipo vector<G>
come argomento:
template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome);
Sfortunatamente, non esiste davvero un modo migliore per farlo.Non è propriamente un difetto del linguaggio, dato che c'è una buona ragione per proibirlo, ma in realtà ti impedisce di fare quello che vuoi in questo contesto.
Altri suggerimenti
Il membro TypeDef type
è un nome dipendente: il suo significato dipende dal parametro modello G
.È necessario utilizzare un typename
per informare il compilatore che type
Nomi A Tipo:
const typename Chromosome<G>::type&
.
Per la spiegazione completa, prendere in considerazione la possibilità di leggere la stack overflow C ++ FAQ Articolo, Dove mettere il" modello "e" typename "sui nomi dipendenti .
AS @TemplateTedef allude nei commenti, mentre ciò abiliterà il codice di compilare, non "funzionerà" per consentire di inserire un std::vector<G>
in un std::ostream
in un type
è in un contesto non dedotto.
Il modo più semplice per dichiarare il sovraccarico e ottenere il comportamento previsto è utilizzare std::vector<G>
direttamente come tipo argomento:
template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome)
.