Anfängerfrage Template
-
Hallo zusammen,
ich soll eine Liste schreiben, welche sowohl ein T als auch ein T & (Referenz) speichern kann. Die Liste soll folgende Funktionen bereitstellen:
void add(T elem), T& get(int index), bool contains(T& elem), void remove(int index); size_t size();das ganze wollte ich über eine std::vector abbilden, leider scheitere ich schon da:
template <typename T> class List { public: void add(T elem); T& get(int index); bool contains(T& elem); void remove(int index); size_t size(); private: typedef std::vector<T> AList; AList list; }Der Compiler will weder die get Methode, noch meine Definition von der list. Von der Implementierung will ich gar nicht erst reden. Kann mir jemand einen Tip geben? Danke

-
Was ist dein Problem?
- Semikolon hinter '}'
-
Warum willst Du das überhaupt machen? Nur die Namen ändern? Alles was Du da an Funktionen aufführst ist doch in std::list schon vorhanden. Wozu die Kapselung? Und mit ; am Ende kompilierts auch.
rya.
-
uwerothfeld schrieb:
ich soll eine Liste schreiben, welche sowohl ein T als auch ein T & (Referenz) speichern kann.
als generelle Anmerkung:
Du kannst std::vector nicht mit einer Referenz verwenden...
Bei std::list bin ich nicht sicher, aber ich glaube auch nicht...
-
Kein Std-Container kann Referenzen von Haus aus speichern. Wozu auch?
-
Hallo zusammen,
also Referenzen speichern geht nicht. Ok.
Als Fehler bekomme ich genau:
g++ -c -g -Werror -MMD -MP -MF build/Debug/GNU-Linux-x86/main.o.d -o build/Debug/GNU-Linux-x86/main.o main.cc /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/ext/new_allocator.h: In instantiation of ‘__gnu_cxx::new_allocator<A::B::Peer&>’: /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/allocator.h:83: instantiated from ‘std::allocator<A::B::Peer&>’ /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_vector.h:78: instantiated from ‘std::_Vector_base<A::B::Peer&, std::allocator<A::B::Peer&> >’ /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_vector.h:159: instantiated from ‘std::vector<A::B::Peer&, std::allocator<A::B::Peer&> >’ common/../PeerList.h:48: instantiated from ‘A::B::PeerList<A::B::Peer&>’ main.cc:34: instantiated from hereWas immer das auch heißen soll. Die Ziele 48 ist:
typedef std::vector<T> AList; AList list;Warum ich dies mache? Also das eigentliche Ziel ist die Verwaltung einer Gruppe, welche in Teilgruppen zerlegt ist. Jede Teilgruppe hat nun so eine Liste, wo es die einzelnen Element speichert. Ich verwende nicht direkt std::vector, da dies so einfacher zu benutzen ist, für mich. Außerdem sollen noch ein paar Funktionen dazu, die so std::vector nicht bietet. Referenzen wollte ich speichern, damit, wenn man sich ein Element aus einer Teilgruppe holt (via: Gruppe.getTeilgruppe(2).getElement(2) ) und dieses ändert, diese Änderungen auch in der Gruppe bestehen (also keine Änderungen an lokalen Kopien gemacht werden).
Oder gibt es da ein besseres Konzept?
Gruß, Uwe
PS: Warum können stl container eigentlich keinen Referenzen speichern?
-
uwerothfeld schrieb:
Oder gibt es da ein besseres Konzept?
Nein, das ist eigentlich schon okay. Du kannst allerdings immer noch Referenzen zurückliefern, auch wenn intern Zeiger gespeichert werden.
Hast du
<vector>eingebunden? Zeig nochmals den kompletten Code der Klassendefinition.uwerothfeld schrieb:
PS: Warum können stl container eigentlich keinen Referenzen speichern?
Weil Referenzen keine Objekte sind und damit etliche Einschränkungen mit sich bringen (z.B. keine Wertsemantik und nicht adressierbar).
-
Hallo Nexus,
hier mal der ganze Code.
#ifndef _PEERLIST_H #define _PEERLIST_H #include "Peer.h" #include <vector> #include "stddef.h" namespace A { namespace B { template <typename T> class PeerList { public: PeerList(); virtual ~PeerList(); size_t size() const; bool contains(T a) const; bool contains(PeerID id) const; T get(size_t index) const; T get(PeerID id) const; void toIntArray(int* destList); T operator [](unsigned int n); void add(T a); void clear(); void remove(T a); void remove(PeerID pId); private: typedef std::vector<T> PList; PList queue; }; }; }; #endif /* _PEERLIST_H */Vielen Dank!
Uwe
-
uwerothfeld schrieb:
hier mal der ganze Code.
Das ist nicht der ganze Code, zumal Templates immer im Header definiert werden müssen (Eine Aufteilung in Header/Source funktioniert nicht - oder nur mit Klimmzügen, wie Include der Source am Dateiende... [Dann aber bitte keine using namespaces usw.]).
-
Ich hatte zwar nur nach der Klassendefinition gefragt, aber es ist dennoch merkwürdig, dass du nicht am Ende noch eine andere Headerdatei mit den Methodendefinitionen inkludierst. Das wäre nämlich eine übliche Technik bei Templates, um trotzdem Schnittstelle und Implementierung zu trennen.
Davon abgesehen ein paar andere Fragen und Vorschläge:
#ifndef _PEERLIST_HDu solltest in C++ keine Bezeichner mit Unterstrich und Grossbuchstaben am Anfang oder mit zwei aufeinanderfolgenden Grossbuchstaben wählen. Nimm doch
PEERLIST_Hoder eindeutigerMEINPROJEKT_PEERLIST_H.#include "stddef.h"In C++ heisst der Header
<cstddef>.virtual ~PeerList();Ist die Klasse für Polymorphie vorgesehen? Dann ist der Destruktor leer, oder?
bool contains(T a) const; void remove(T a);Hier hast du unnötige Kopien, verwende stattdessen Const-Referenzen (
const T&).T get(size_t index) const; T operator [](unsigned int n);Warum zwei Methoden für das gleiche, aber mit komplett anderer Schnittstelle (
size_tvs.unsigned int,constvs. veränderlich, andere Parameternamen)? Ich würde die Schnittstelle nicht grösser als nötig machen. Ausserdem kann es ratsam sein, eineconst-Überladung anzubieten, die das Objekt nicht verändert, und nebenbei eine mit Referenzrückgabe (T&).
-
hallo zusammen,
vielen Dank für die Tips. Einiges konnte ich beheben, aber das Thema Template ist schon etwas komplexer, als gedacht.
gruß, uwe