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>>() als friend innerhalb der Klasse definierst, geht es ohne typename.



  • @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üsste typename 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 🙂


  • Mod

    @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),


Anmelden zum Antworten