Enumerable<T> Adaption aus C#



  • Hallo Leute,

    ich wollte euch mal etwas vorstellen und mir Kritik und Meinungen einholen.
    Da ich aus der C# Ecke komme und jetzt wieder zu meinen Wurzeln(C++) zurueck gefunden habe, wollte ich mir etwas aehnliches wie die Enumerable Klasse aus C# implementieren.
    Ich bin erstmal ganz naiv ran gegangen und habt das mit einer internen std::list gemacht, und hab mir so ein paar wichtige Funktionen wie where mit in das oeffentliche Interface der Klasse reingenommen.

    #ifndef ENUMERABLE_H_INCLUDED
    #define ENUMERABLE_H_INCLUDED
    
    #include <list>
    #include <functional>
    #include <iostream>
    template<typename T>
    class Enumerable
    {
    	private:
    		std::list<T> list;
    	public:
    		typedef typename std::list<T>::iterator iterator;
    		typedef typename std::list<T>::const_iterator const_iterator;
    	public:
    		Enumerable();
    		Enumerable(const Enumerable& enumerable);
    		Enumerable(typename std::list<T>::const_iterator begin,typename std::list<T>::const_iterator end);
    		Enumerable where(std::tr1::function<bool (const T& value)>)const;
    		void sort(std::tr1::function<bool (const T&, const T&)>);
    		void push_back(const T& value);
    		void remove(const T& value);
    		void clear();
    		iterator begin();
    		iterator end();
    
    		const_iterator begin() const;
    		const_iterator end() const;
    		size_t size() const;
    };
    
    template<typename T>
    Enumerable<T>::Enumerable(){}
    
    template<typename T>
    Enumerable<T>::Enumerable(typename std::list<T>::const_iterator begin,typename std::list<T>::const_iterator end)
    {
    	this->list.assign(begin, end);
    }
    
    template<typename T>
    Enumerable<T>::Enumerable(const Enumerable& enumerable)
    {
    	this->list.assign(enumerable.begin(), enumerable.end());
    }
    
    template<typename T>
    Enumerable<T> Enumerable<T>::where(std::tr1::function<bool (const T& value)> predicate)const
    {
    	std::list<T> temp;
    	typename std::list<T>::const_iterator begin = this->list.begin();
    	typename std::list<T>::const_iterator end = this->list.end();
    	while(begin != end)
    	{
    		if(predicate(*begin))
    		{
    			temp.push_back(*begin);
    
    		}
    		begin++;
    
    	}
    
    	return Enumerable<T>(temp.begin(), temp.end());
    }
    
    template<typename T>
    void Enumerable<T>::sort(std::tr1::function<bool (const T&, const T&)> sorter)
    {
    	this->list.sort(sorter);
    }
    
    template<typename T>
    void Enumerable<T>::push_back(const T& value)
    {
    	this->list.push_back(value);
    }
    
    template<typename T>
    typename Enumerable<T>::iterator Enumerable<T>::begin()
    {
    	return this->list.begin();
    }
    
    template<typename T>
    typename Enumerable<T>::iterator Enumerable<T>::end()
    {
    	return this->list.end();
    }
    template<typename T>
    size_t Enumerable<T>::size() const
    {
    	return this->list.size();
    }
    template<typename T>
    typename Enumerable<T>::const_iterator Enumerable<T>::begin() const
    {
    	return this->list.begin();
    }
    template<typename T>
    typename Enumerable<T>::const_iterator Enumerable<T>::end() const
    {
    	return this->list.end();
    }
    template<typename T>
    void Enumerable<T>::remove(const T& value)
    {
    	this->list.remove(value);
    }
    
    template<typename T>
    void Enumerable<T>::clear()
    {
    	this->list.clear();
    }
    
    #endif // ENUMERABLE_H_INCLUDED
    

    Ich weiß das hier noch ein paar Funktionen fehlen, aber ich wollte einfach mal in den Wald reinhorchen und fragen ob ihr noch Anregungen fuer mich habt.



  • Was ist der Vorteil gegenüber rohen Containern wenn ich fragen darf?



  • Ich weiß das man mit den Standard-Algorithmen sicherlich so einen Mechanismus des "Where" abdecken kann. Aber mir persoenlich gefaellt es besser wenn ich eine Methode und Klasse habe die diese Logik kapseln. Ich sagte auch bereits das hier noch diverse Methoden fehlen.

    Siehe http://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods.aspx

    Das ist in etwa der Umfang den ich anbieten moechte.



  • Okay, dann bau zumindestens den Container-Typ als Template-Parameter ein (kannst ja einen Default nehmen) und bau alles so um, dass ein Enumerable<int, std::vector> auch mit einem Enumerable<int, std::list> etc funktioniert. 🙂



  • Ethon schrieb:

    Okay, dann bau zumindestens den Container-Typ als Template-Parameter ein (kannst ja einen Default nehmen) und bau alles so um, dass ein Enumerable<int, std::vector> auch mit einem Enumerable<int, std::list> etc funktioniert. 🙂

    Das ist ne super Idee, danke fuer den Hinweis.



  • In LINQ gibt es im Gegensatz zu deiner Klasse kein push_back/remove/clear. Weil es auf Enumerationen keinen Sinn macht!




Anmelden zum Antworten