Template, Liste, Funktion
-
Kannst du mir bei der Instanziierung helfen?
Weiß nciht an welcher Stelle und wie die Syntax genau ist..
-
Darum geht es nicht.
@spiegelbirke2 sagte in Template, Liste, Funktion:
List<T0>::Node* last;
~>
typename List<T0>::Node* last;
Was anderes. Ich würde bei so Zeugs immer mit den elementarsten Funktionen und bei denen mit den "Ausnahmen" (leere Liste) anfangen:
#include <utility> #include <stdexcept> #include <iostream> template<typename T> class List { struct Node { // sollte in der Regel nicht public sein. Interna gehen T value; // den Benutzer der List nichts an. Node *prev; Node *next; Node(T value = T{}, Node *prev = nullptr, Node *next = nullptr) : value { value }, prev { prev }, next { next } {} }; Node *head = nullptr; Node *tail = nullptr; std::size_t length = 0; public: List() = default; List(List<T> const &other) { if (!other.length) return; head = tail = new Node{ other.head->value }; for (Node *write_pos{ head }, *read_pos{ other.head->next }; read_pos; read_pos = read_pos->next, write_pos = write_pos->next) tail = write_pos->next = new Node{ read_pos->value, write_pos }; length = other.length; } friend void swap(List<T> &first, List<T> &second) { using std::swap; swap(head, second.head); swap(tail, second.tail); swap(length, second.length); } List<T>& operator=(List<T> other) { swap(*this, other); return *this; } void clear() { for (auto current = head; current; ) { auto next = current->next; delete current; current = next; } head = tail = nullptr; length = 0; } ~List() { clear(); } bool empty() const { return !length; } void push_front(T const &value) // Zuerst das Einfachste. { head = new Node{ value, nullptr, head }; if (head->next) // wenn head einen nachfolger hat head->next->prev = head; // prev des nachfolgers anpassen else tail = head; // sonst ist das Ding leer und der Schwanz ist der Kopf. ++length; } void push_back(T const &value) { if (!length) { // push_back() auf eine leere Liste ist das selbe wie push_front() push_front(value); return; } tail->next = new Node{ value, tail }; if(tail->prev) // wenn der Schwanz einen Vorgänger hat tail->prev->next = tail; // den next des Vorgängers anpassen tail = tail->next; ++length; } void insert(std::size_t position, T const &value) { if (position > length) throw std::range_error{ "List<T>::insert(): position out of range!" }; if (!position) { // insert an Position 0 ist push_front() push_front(value); return; } if (position == length) { // insert an Position length ist push_back() push_back(value); return; } Node *at = head; // sonst durchlatschen und mitzählen for (std::size_t i{ 1 }; i < position; ++i) at = at->next; at->next = new Node{ value, at, at->next }; ++length; } friend std::ostream& operator<<(std::ostream &os, List<T> const &list) { if (list.empty()) return os; std::cout << list.head->value; for (auto current = list.head->next; current; current = current->next) os << ' ' << current->value; return os; } friend std::istream& operator>>(std::istream &is, List<T> &list) { list.clear(); // solange Ts von is gelesen werden können an die Liste anhängen: for (T value; is >> value; list.push_back(value)); return is; } };
-
Okay.. ja klar, Sorry..
Was ich halt nicht verstehe ist, dass der Code eine Musterlösung von unserem Prof ist. Ich habe es 1zu1 nachprogrammiert.Die Klasse List fehlt halt und ich glaube, dass es auch 1zu1 möglich sein müsste, den Code zu kompilieren, ohne 'typename' , mit einer selbst geschriebenen Klasse.
-
Wenn Du den
operator>>()
alsfriend
innerhalb der Klasse definierst, geht es ohnetypename
.
-
@spiegelbirke2 Visual C++ frisst den Code auch ohne
typename
- trotz dem er falsch ist. Und ganz aktuelle Visual C++ Versionen spucken dir hier ebenfalls einen Fehler aus wenn du mit/permissive-
oder/Zc:twoPhase
compilierst.Und GCC und Clang werden es grundsätzlich nicht compilieren. Ausgenommen vielleicht sehr alte Versionen oder evtl. Clang im Visual C++ Kompatibilitätsmodus.
-
@hustbaer Das heißt auch bei meiner "Lösung" für mit ohne
typename
müsstetypename
hin?
-
@Swordfish Ehrlich gesagt: weiss ich nicht. Ich hab' mich auf den von @spiegelbirke2 geposteten Code bezogen. Ich schätze die Version mit
friend
dürfte OK sein. Vielleicht
-
@hustbaer sagte in Template, Liste, Funktion:
Vielleicht
Ach, diese Sprache muss man einfach lieben!
-
Naja ne das wird schon klar aus dem Standard hervorgehen. Hab das nicht nachgelesen. Es fressen dann aber alle Compiler die ich probiert habe: MSVC (auch mit
/permissive-
), GCC 8.3 und Clang 8.0.
-
Mit meinem Kommentar bezog ich mich nicht darauf daß es nirgends geschrieben steht, sondern darauf daß keine S** auf die schnelle rausfinden kann wo. *lol*
-
Naja, hab's nicht versucht, aber auf mich bezogen wirst du Recht haben. @Columbo findet das sicher in < 1 Minute
-
@hustbaer Aus [basic.lookup.unqual]:
Name lookup for a name used in the definition of a friend function defined inline in the class granting friendship shall proceed as described for lookup in member function definitions.
Und [temp.dep.type]/1:
A name refers to the current instantiation if it is ... in the definition of a primary class template or a member of a primary class template, the name of the class template followed by the template argument list of the primary template (as described below) enclosed in <> (or an equivalent template alias specialization),