templates + inline



  • Hallo,

    warum kann ich template-spezialisierungen mit inline verwenden?
    Mir ist klar dass wenn ich die spezialisierungen in die klasse (header) packe
    dass dann alles inline ist. aber warum kann ich es nicht außerhalb der klasse wie mit "normalem" template-freien code?

    Hier ein Beispiel

    #include <iostream>
    
    template<class T> class MyClass
    {
            public:
                MyClass<T>() { }
            intline T foo() { };
    };
    
    template<> inline double MyClass<double>::foo()
    {
            return 1.0;
    }
    
    template<> inline int MyClass<int>::foo()
    {
            return 1;
    }
    
    int main(int argc, char *argv[])
    {
    
      MyClass<int> m = MyClass<int>();
      std::cout << m.foo() << std::endl;
      return 0;
    }
    


  • inline geht, intline nicht 😉



  • ah scheiße - danke



  • testo schrieb:

    aber warum kann ich es nicht außerhalb der klasse wie mit "normalem" template-freien code?

    Kannst du doch.

    (Die Antwort war jetzt ungefähr so informativ wie dein "kann ich nicht". Ne Fehlermeldung wäre nächstemal Klasse ;))

    Du kannst nur nicht Teile eines Klassentemplates spezialisieren, d.h. du musst das komplette Klassentemplate spezialisieren.



  • jetzt bin ich wieder verwirrt.
    was meinst du mit Teile eines klassentemplates?

    ich habe jetzt das problem dass mein minimalbeispiel funktioniert aber mein Hauptcode wegen undefined references nicht linkt.

    Also bei dem Minimalbeispiel gehts unten aber bei meinem hauptcode sobald ich da foo in bar() aufrufe schreit beim compilier bzw. linkervorgang mit
    undefined reference to.

    Deshalb meine Frage: Was könnte ich übersehen haben im hauptcode?

    #include <iostream>
    
    template<class T> class MyClass
    {
            public:
                MyClass<T>() { }
            inline double foo() { };
            void bar();
    };
    
    template<> inline double MyClass<double>::foo()
    {
            return 1.0;
    }
    
    template<> inline double MyClass<int>::foo()
    {
            return 1.0;
    }
    
    template<class T> void MyClass<T>::bar()
    {
            double a = foo();
            std::cout << a << std::endl;
    }
    
    int main(int argc, char *argv[])
    {
    
      MyClass<int> m = MyClass<int>();
      m.bar();
      return 0;
    }
    


  • testo schrieb:

    Also bei dem Minimalbeispiel gehts unten aber bei meinem hauptcode sobald ich da foo in bar() aufrufe schreit beim compilier bzw. linkervorgang mit
    undefined reference to.

    Bitte liefere uns die komplette Fehlermeldung, nicht nur das "undefined reference to". Sonst kann man nur raten was schief läuft.

    Hast du die kompletten Template-Definitionen im Header?



  • testo schrieb:

    jetzt bin ich wieder verwirrt.
    was meinst du mit Teile eines klassentemplates?

    Hab ich mich wohl geirrt, ich war der Meinung, du könntest nicht nur eine Methode des template spezialisieren sondern müsstest wenn dann die ganze Klasse spezialisieren. Offenbar kann zumindest gcc das aber doch...



  • bitte um entschuldigung aber ich kann den ganzen code nicht posten.

    Hast du die kompletten Template-Definitionen im Header?
    

    ich muss doch gar nicht die ganze definition im header haben oder?
    lagere ich z.B. dashier in ein cpp file:

    #include "MyClass.h"
    
    template<> inline double MyClass<double>::foo()
    {
            return 1.0;
    }
    
    template<> inline double MyClass<int>::foo()
    {
            return 1.0;
    }
    

    und das hier in ein imp.h file:

    template<class T> void MyClass<T>::bar()
    {
        double a = foo();
        std::cout << a << std::endl;
    }
    

    und mein MyClass.h sieht so aus:

    template<class T> class MyClass
    {
        public:
            MyClass<T>() { }
        inline double foo() { };
        void bar();
    };
    
    #include "MyClass.imp.h"
    

    dann funktioniert alles. In meinem Hauptcode allerdings nicht. Dort MUSS ich seltsamerweise was mich eben verwirrt 😕 die Definition im Header drin stehen haben mit inline. Dann kann ich mir aber eigentlich das inline doch sparen oder nicht?
    Also mein Problem liegt darin, dass das minimalbeispiel eben was anderes ausspuckt (korrekt) als mein Hauptcode (undefined reference).
    Ich hab im hauptcode nur eine ganz einfach template<> inline void MyClass<int>::test() funktion eingefügt ins cpp file. sobald ich test() einfach in einer funktion in der datei imp.h aufrufe gibts undefined reference.
    seltsam...



  • Hast du die kompletten Template-Definitionen im Header?

    Genau das solltest du testen.

    Es hat mal Versuche gegeben das anders zu realisieren. Die sind bei den Compileranbietern aber kaum umgesetzt und inzwischen wieder aus der C++ Norm entfernt. Kümmere mich wenig um diese Normen - hoffe das das passt.

    MfG f.-th.



  • testo schrieb:

    bitte um entschuldigung aber ich kann den ganzen code nicht posten.

    Die Fehlermeldung, nicht den Code. Den Code könntest du aufs Wesentliche reduzieren, d.h. unwichtige Dinge wegstreichen, so dass am Ende nur das problem übrig bleibt.

    testo schrieb:

    Hast du die kompletten Template-Definitionen im Header?
    

    ich muss doch gar nicht die ganze definition im header haben oder?

    Indirekt schon. In deinem Fall kannst du vollständige Spezialisierungen (aber auch nur die) zwar in einer .cpp definieren, musst sie aber irgendwo deklarieren. Sonst weiß der Compiler beim Übersetzen nicht, dass es die Spezialisierungen gibt und instantiiert einfach das normale template, und das ist ja genau das, was du durch die Spezialisierungen ändern willst.



  • f.-th. schrieb:

    Es hat mal Versuche gegeben das anders zu realisieren. Die sind bei den Compileranbietern aber kaum umgesetzt und inzwischen wieder aus der C++ Norm entfernt. Kümmere mich wenig um diese Normen - hoffe das das passt.

    Es (das keyword export und die zugehörige Funktionalität) ist von exakt einem Compilerhersteller umgesetzt worden. Im kommenden C++0x-Standard ist export nicht mehr gültig (das keyword aber immernoh reserviert).


Anmelden zum Antworten