Template-Typ feststellen



  • otze schrieb:

    gibt viele möglichkeiten.

    die erste wäre, die funktion zu überladen:

    void Out<float>(float &vektor){
    //hier wissen wir,d ass float gemeint ist
    }
    

    Das ist keine Überladung sondern eine explizite Spezialisierung mit fehlendem template<>.

    da ich nicht weis, was du machen willst, zeig ich einfach mal verschiedene beispiele auf:

    Wenn du Zeit hast, mach doch mal die verschiedenen Fehler raus.

    Mir scheints am besten zu sein, ich übergebe einfach noch nen string:

    Das hört sich für mich noch viel Schlimmer an. Damit verlierst du gleich noch die statische Typprüfung und verschiebst Compilezeit- zu Laufzeit-Fehlern.

    Was willst du denn eigentlich machen?



  • otze schrieb:

    alternativ kann man sowas machen:

    template <class T> void Out<vector<T> >(vector<T> &vektor)
    {
        T i = T();  
        ...
    }
    

    In welcher Sprache? Otze++? Also in C++ kann man das nicht machen.

    auch lustig ist sowas:

    template<template<class> class T,class U>
    void Out<T<U> >(T<U> &vector){
        typedef T ContainerType;
        typedef U ValueType;
    }
    

    Ja. Sehr lustig. Und vorallem kein Standard-C++. Und noch dazu Template-Template-Parameter die sowieso nicht portabel mit std-Containern arbeiten.

    Manchmal ist weniger mehr...



  • Danke für die Antworten.
    Die Lösung mit

    if (typeid(int) == typeid(T))
    ...
    

    funktioniert sehr gut.
    Ich habe die (schlechte) Variante mit der Übergabe des strings mal probiert, nur so zum Testen. Das Programm lief damit auch ganz einwandfrei. Hätte es das nicht tun sollen? Steh da etwas auf dem Schlauch.
    Ich brauche das alles für matrizenähnliche Berechnungen. Der Code ist zu 99% unabhängig für float und int, nur an wenigen Zeilen muss ich eine Änderung in Abhängigkeit für float und int vornehmen, daher wollte ich doch ganz gerne nicht zwei verschiedene Funktionen verwenden.



  • Zeig doch mal den Code und verseh die entsprechenden Knackpunkte mit einem
    Kommentar. Vielleicht faellt hier jemandem eine geeignete Loesung fuer dein
    Problem ein, die auch noch schoen umzusetzen ist.

    mfg
    v R



  • Ingo schrieb:

    Danke für die Antworten.
    Die Lösung mit

    if (typeid(int) == typeid(T))
    ...
    

    funktioniert sehr gut.
    Ich habe die (schlechte) Variante mit der Übergabe des strings mal probiert, nur so zum Testen. Das Programm lief damit auch ganz einwandfrei. Hätte es das nicht tun sollen? Steh da etwas auf dem Schlauch.
    Ich brauche das alles für matrizenähnliche Berechnungen. Der Code ist zu 99% unabhängig für float und int, nur an wenigen Zeilen muss ich eine Änderung in Abhängigkeit für float und int vornehmen, daher wollte ich doch ganz gerne nicht zwei verschiedene Funktionen verwenden.

    Stringvergleiche kosten dich immer Laufzeit.
    Sinnvoller wäre dann eine Enum, in der du feste Werte hast.

    Devil



  • @Hume erst maulen, wenn der eigene code funktioniert:

    template <class T> void Out(T &vektor)
    {
        typedef typename T::value_type ValType;
        ValType i = ValType();  
    }
    
    Compiling...
    test.cpp
    test.cpp: In function `void Out(T&) [with T = std::vector<int,
    std::allocator<int> >]':
    test.cpp:11:   instantiated from here
    test.cpp:7: warning: unused variable `int i'
    
    test.o - 1 error(s), 1 warning(s)
    

    🙄

    aber hast recht, partial specialisation geht bei funktionen nicht 😉

    Und noch dazu Template-Template-Parameter die sowieso nicht portabel mit std-Containern arbeiten.

    hmm, beim gcc funktionierten bisher folgende versionen:

    template<template<class,class> class T,class U,class A>
    void Out(T<U,A> &vektor){
        typedef T<U,A> ContainerType;
        typedef U ValueType;
    }
    

    und

    template<template<class> class T,class U>
    void Out(T<U> &vektor){
        typedef T<U> ContainerType;
        typedef U ValueType;
    }
    

    den zweiten template parameter von vector kann der gcc sich scheinbar selber herleiten.



  • otze schrieb:

    @Hume erst maulen, wenn der eigene code funktioniert:

    Compiling...
    test.cpp
    test.cpp: In function `void Out(T&) [with T = std::vector<int,
    std::allocator<int> >]':
    test.cpp:11:   instantiated from here
    test.cpp:7: warning: unused variable `int i'
    
    test.o - 1 error(s), 1 warning(s)
    

    Sehe keinen Fehler - kannst du es mir bitte erklären woher "1 error" kommt?

    hmm, beim gcc funktionierten bisher folgende versionen:

    Weisst du was portabel heisst?

    Das Problem ist, dass std Container beliebig viele Template-Parameter nehmen können - der Code ist also nicht Standardkonform und somit nicht portabel.

    den zweiten template parameter von vector kann der gcc sich scheinbar selber herleiten.

    Hast du -std=c++98 als Parameter angegeben?
    Hab leider keinen gcc hier um es zu testen - aber Comeau ist nicht deiner Meinung, der behauptet (korrekterweise) dass der Code illegal ist - weil vector eben noch einen Allocator hat.



  • Ingo schrieb:

    Ich brauche das alles für matrizenähnliche Berechnungen. Der Code ist zu 99% unabhängig für float und int, nur an wenigen Zeilen muss ich eine Änderung in Abhängigkeit für float und int vornehmen.

    Vielleicht sind traits die Lösung?

    Aber dazu mußt Du etwas genauer erklären, was Du erreichen willst.

    MfG Jester



  • Ingo schrieb:

    Ich brauche das alles für matrizenähnliche Berechnungen. Der Code ist zu 99% unabhängig für float und int, nur an wenigen Zeilen muss ich eine Änderung in Abhängigkeit für float und int vornehmen, daher wollte ich doch ganz gerne nicht zwei verschiedene Funktionen verwenden.

    Genau das wäre aber imo die beste Lösung. Nicht umsonst bietet C++ solche netten Dinge wie Überladung und Spezialisierung an. Die Codesequencen, die gleich sind, kannst du ja in inline Funktionen auslagern, genauso ist das natürlich umgekehrt mit den unterschiedlichen Codesequencen möglich.



  • Shade Of Mine schrieb:

    Sehe keinen Fehler - kannst du es mir bitte erklären woher "1 error" kommt?

    frag mich nicht,habs nur in ein neues projekt copy-pastet und dann aufgerufen, nachdem ich in meiner funktion genau an derselben stelle den fehler hatte( T() bzw ValType())

    Hast du -std=c++98 als Parameter angegeben?

    g++.exe -std=c++98 -Wall -o "C:/test/test.exe" "C:test/test.cpp"
    bin mir nicht 100% sicher ob der aufruf so richtig ist, aber es funktioniert^^
    ich bekomm aber das selbe ergebnis, wenn ich im MinGW unter den exra compiling options -std=c++98 angebe, aber auch da bin ich mir nicht 100% sicher 🙄
    hab mich beim gcc noch nicht mit den aufrufkonventionen beschäftigt 🙂



  • otze schrieb:

    Shade Of Mine schrieb:

    Sehe keinen Fehler - kannst du es mir bitte erklären woher "1 error" kommt?

    frag mich nicht,habs nur in ein neues projekt copy-pastet und dann aufgerufen, nachdem ich in meiner funktion genau an derselben stelle den fehler hatte( T() bzw ValType())

    Comeau findet keinen Fehler - und deine Ausgabe zeigt nur eine Warnung an...

    Hast du -std=c++98 als Parameter angegeben?

    g++.exe -std=c++98 -Wall -o "C:/test/test.exe" "C:test/test.cpp"
    bin mir nicht 100% sicher ob der aufruf so richtig ist, aber es funktioniert^^
    ich bekomm aber das selbe ergebnis, wenn ich im MinGW unter den exra compiling options -std=c++98 angebe, aber auch da bin ich mir nicht 100% sicher 🙄
    hab mich beim gcc noch nicht mit den aufrufkonventionen beschäftigt 🙂

    Interessant, mach mal mit

    -std=c++98 -Wall -W -pedantic

    Oder vertraue Comeau (dem standardkonformsten aller Compiler)



  • Comeau findet keinen Fehler - und deine Ausgabe zeigt nur eine Warnung an...

    *schulterzuck* hab mich auch gewudnert, dieser nicht angezeigte fehler war aber weg, nachdem man ValType()/T() entfernt hat.

    //edit es blieben aber nur 2 warnings, nachdem ich den code nicht über mingw kompiliert hab, scheint ein bug zu sein, sollte man melden^^

    @hume sorry

    -std=c++98 -Wall -W -pedantic

    selbes ergebnis

    Oder vertraue Comeau (dem standardkonformsten aller Compiler)

    muss man wohl...



  • Ok, ich habe mal einen Baustein genommen.
    Ich möchte ein Iterations-Zwischenergebnis ausgeben. Dafür brauche ich einen string s.
    Statt int verwende ich meine eigene kleine Klasse "frac", also Brüche. Das mit dem int habe ich nur gesagt, weil es mein Problem prägnanter verdeutlichte. Es drehte sich bei mir also immer um float vs. fraction.

    template <class T> void Ausgeben_Iterationszwischenergebnis(const T &m_arr, const int m_zeilen, const int m_spalten)
    {
    	string s;
    	for (int i = 0; i < m_zeilen; i++)
    		for (int j = 0; j < m_spalten; j++)
    			if (typeid(float) == typeid(T))
    			{
    				ostringstream os;
    				os <<m_arr[i][j];
    				string s = os.str();
    			}
    			else //bleibt nur Bruch als Alternative übrig
    			{
    				frac f = m_arr[i][j];
    				s = f.getstr();
    			}
    	//Ausgabe starten... ab hier wieder größtenteils unabhängig
    

    Um an s zu kommen, musste ich wissen, was für ein Typ vorlag. Jetzt kann ich wieder größtenteils unabhängig weitermachen.



  • Okay, dann isses einfach. Definier Dir einfach einen op<< für Deine Klasse frac:

    in etwa so:

    std::ostream & operator<<(std::ostream & os, frac const& f)
    {
      os << f.getZaehler() << '/' << f.getNenner();
      return os;
    }
    

    und schon funktioniert der Code für den float für beide.

    MfG Jester


Anmelden zum Antworten