Typedef- und Ostream-Operator für einen std::vector
Frage
Ich habe eine Klasse „Chromosom“ erstellt, die letztendlich lediglich ein Wrapper für „Vektor“ mit einem Ostream-Operator war, also habe ich mich stattdessen für „Typedef Vector“ entschieden.Ich habe jedoch Probleme mit dem Ostream-Operator mit Vorlagen ...Ist das der beste Weg?(Ich habe einige Ansätze gesehen und es nicht geschafft, einen zum Laufen zu bringen)
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;
}
Im Moment erhalte ich folgende Fehlermeldung:
chromosome.h:19: error: expected unqualified-id before ‘&’ token
chromosome.h:19: error: expected ‘)’ before ‘&’ token
chromosome.h:19: error: expected initializer before ‘&’ token
Prost.
Lösung
Leider gibt es dafür keine saubere Möglichkeit, da der Compiler den Typ nicht ableiten kann G
aus der Funktionsdeklaration
template<typename G>
std::ostream& operator<<(std::ostream& os, const typename Chromosome<G>::type& chromosome);
Der Grund dafür ist, dass man sich spezialisieren würde Chromosome
Bei verschiedenen Typen könnte es zu einer Situation kommen, in der der Compiler keine eindeutige Schlussfolgerung ziehen kann G
.Zum Beispiel:
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;
};
Was würde nun passieren, wenn Sie das tun würden?
vector<double> v;
cout << v << endl;
Der Compiler kann nicht sagen, ob G
Ist double
oder int
in diesem Fall, weil beides Chromosome<int>
Und Chromosome<double>
haben vector<double>
als ihr verschachtelter Typ.
Um dies zu beheben, müssen Sie den Typ explizit verwenden vector<G>
als Argument:
template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome);
Leider gibt es wirklich keine bessere Möglichkeit, dies zu tun.Es handelt sich nicht wirklich um einen Sprachfehler, da es einen guten Grund gibt, ihn zu verbieten, aber er hindert Sie tatsächlich daran, in diesem Zusammenhang das zu tun, was Sie wollen.
Andere Tipps
Die Mitgliedstypdefinition type
ist ein abhängiger Name:Seine Bedeutung hängt vom Vorlagenparameter ab G
.Sie müssen a verwenden typename
um das dem Compiler mitzuteilen type
benennt einen Typ:
const typename Chromosome<G>::type&
Eine vollständige Erklärung finden Sie im FAQ-Artikel zu Stack Overflow C++: Wo werden „template“ und „typename“ für abhängige Namen eingefügt?.
Wie @templatetypedef in den Kommentaren andeutet, ermöglicht dies zwar die Kompilierung des Codes, es funktioniert jedoch nicht, Ihnen das Einfügen eines Codes zu ermöglichen std::vector<G>
In ein std::ostream
Weil type
steht in einem nicht abgeleiteten Kontext.
Der einfachste Weg, die Überladung zu deklarieren und das erwartete Verhalten zu erhalten, ist die Verwendung von std::vector<G>
direkt als Argumenttyp:
template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome)