Template Spezialisierung für Memberfunction



  • Nexus schrieb:

    Zur Default-Konstruierbarkeit habe ich oben noch etwas gesagt. Hängt halt davon ab, wie generisch dein Code sein soll.

    Stimmt, grad gelesen. Ich würde es gerne nicht als Bedingung angeben, aber gibt es in C++ Templates solche Constraints wie C# Generics? Ich weiß es grad nicht.

    Wobei mir grad einfällt, ein Defaultctor wäre schon ne feine Sache und als zweite Bedingung nen Überladenen >> Operator wäre auch ganz fein, aber wie gesagt, wie kann ich das definieren?



  • Firefighter schrieb:

    Wobei mir grad einfällt, ein Defaultctor wäre schon ne feine Sache und als zweite Bedingung nen Überladenen >> Operator wäre auch ganz fein, aber wie gesagt, wie kann ich das definieren?

    dokumentiers. wenn die Operationen fehlen, wird der Compiler schon meckern. Mehr geht nicht.



  • Firefighter schrieb:

    Stimmt, grad gelesen. Ich würde es gerne nicht als Bedingung angeben, aber gibt es in C++ Templates solche Constraints wie C# Generics?

    Keine Ahnung wie das in C# genau aussieht, aber du hast in C++ Type-Traits. Concepts waren auch mal eine Diskussion, aber die kommen vorerst noch nicht in die Sprache.

    Firefighter schrieb:

    Wobei mir grad einfällt, ein Defaultctor wäre schon ne feine Sache und als zweite Bedingung nen Überladenen >> Operator wäre auch ganz fein, aber wie gesagt, wie kann ich das definieren?

    Du musst das gar nicht explizit definieren. Code, der die Anforderungen nicht erfüllt, kompiliert nicht.



  • Nexus schrieb:

    Du musst das gar nicht explizit definieren. Code, der die Anforderungen nicht erfüllt, kompiliert nicht.

    Vollkommen korrekt, ganz vergessen. Gut dann nehm ich das Type2Type struct jetzt raus und lass T als Parameter bei der readImpl.



  • Wenn du eh nur einen generischen Fall hast, kannst du readImpl() auch gleich rausschmeissen und direkt read() verwenden.



  • Joa schon, ok ich dank euch fürs erste. 🙂



  • Wollte nochmal die ganze bisherige Lösung präsentieren.
    Um ehrlich zu sein gefällt die mir gar nicht. Fühl mich nich gut beim anschauen der Lösung 😃 Habt ihr noch anmerkungen?

    class Input
    {
    	private:
    		Input(){}
    
    		template<class T>
    		static void getInput(T& object)
    		{
    			std::ios_base::iostate state;
    
    			while(!(std::cin>>object))
    			{
    				std::cout<<"Wrong format, please try again!"<<std::endl;
    				std::cin.clear();
    				std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
    			}
    		}
    	public:
    		template<class T>
    		static T read()
    		{
    			T object;
    			getInput(object);
    			return object;
    		}
    
    		static int read(int lowerBound, int upperBound)
    		{
    			if(lowerBound > upperBound)
    				std::swap(lowerBound,upperBound);
    
    			int object;
    			getInput(object);
    			while(object < lowerBound || object > upperBound)
    			{
    
    				std::cout<<"The value does fall not in the expected range!("<<lowerBound<<"-"<<upperBound<<")"<<std::endl;
    				getInput(object);
    			}
    
    			return object;
    		}
    
    };
    


  • Ist eigentlich soweit in ordnung. die state variable kannste entfernen, benutzt du ja nirgendwo. Ich würde das nicht static machen wollen und das Ganze schreit eigentlich danach, daraus freie Funktionen zu machen bzw aus der class Input einen namespace Input zu machen. Wir sind ja nicht in Java :).

    du kannst dir auch überlegen, das zweite Read generischer zu machen, indem du statt int einen beliebigen Typen erlaubst. so kannst du die Funktionen direkt für float, double etc verwenden.



  • Was mir gerade aufgefallen ist:

    • Deine Klasse hat keinen Status und nur statische Methoden (abgesehen vom sinnlosen Konstruktor). Du könntest auch einen Namensraum benutzen, allerdings müsstest du dann die privaten Member in einem detail -Namespace verstecken.
    • Die Variable state wird nicht benutzt.
    • Gibt es einen Grund für das Tauschen der Bounds? Wäre es nicht sinnvoller, richtig übergebene Bounds zu fordern und mit assert sicherzustellen? Ich habe grundsätzlich eine gewisse Abneigung gegen Versuche, Logikfehler gerade zu biegen 😉
    • Warum while(object < lowerBound || object > upperBound) ? Wird diese Bedingung jemals true , falls der erste getInput(object) -Aufruf fehlschlägt? Davon abgesehen entspricht die Struktur eher do-while .


  • Man dankt für die Kritik und wird sie umsetzen 🙂

    Das mit dem Namespace klingt gut, werde ich glaube umsetzen.


Anmelden zum Antworten