Methode kann nicht gefunden werden



  • Hallo Leute,

    folgende Frage:

    CSVDocument.h:

    // ...
    template <class TToken> class CSVDocument;
    template <class TToken> std::ostream& operator<<(std::ostream&, const CSVDocument<TToken>&);
    template <class TToken> std::istream& operator>>(std::istream&, CSVDocument<TToken>&);
    
    template <class TToken>
    class CSVDocument
    {
    	public:
    
    		// ...
    
    		friend std::ostream& operator<< <>(std::ostream& out, const CSVDocument<TToken>& document);
    		friend std::istream& operator>> <>(std::istream& in, CSVDocument<TToken>& document);
    
    };
    

    CSVDocument.cpp:

    #include "CSVDocument.h"
    
    using namespace std;
    
    // ...
    template <class TToken>
    ostream& operator<<(ostream& out, const CSVDocument<TToken>& document)
    {
    	// ....
    	return out;
    }
    
    template <class TToken>
    istream& operator>>(istream& in, CSVDocument<TToken>& document)
    {
    	// ...
    	return in;
    }
    
    // ...
    

    $ make CSVDocument.o
    g++ -Wall -c CSVDocument.cpp CSVDocument.h

    Keine Kompilierfehler 👍

    Main.cpp

    #include <iostream>
    #include <cstdlib>
    #include <fstream>
    #include <string>
    #include "CSVDocument.h"
    
    const char* DATAFILE = "data.csv";
    
    int main(int argc, char *argv[])
    {
    	using namespace std;
    
    	ifstream input(DATAFILE);
    	if (!input)
    	{
    		cerr << "The data file '" << DATAFILE << "' doesn't exist." << endl;
    		exit(EXIT_FAILURE);
    	}
    
    	CSVDocument<string> document;
    	input >> document;
    
    	input.close();
    
    	return EXIT_SUCCESS;
    }
    

    $ make
    g++ -Wall -c Main.cpp
    g++ -Wall -c PNode.cpp PNode.h
    g++ -Wall -o mrsts CSVDocument.o Main.o PNode.o
    Main.o: In function main': Main.cpp:(.text+0xd3): undefined reference tostd::basic_istream<char, std::char_traits<char> >& operator>><std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_istream<char, std::char_traits<char> >&, CSVDocument<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)'
    collect2: ld returned 1 exit status
    make: *** [mrsts] Fehler 1

    Fehler 👎

    Hinweis: Der Fehler tritt auch bei anderen Methoden auf (nutzen auch den istream), nicht nur bei den operatoren.

    Nach mehreren Stunden beim gleichen Fehler bin ich sehr genervt.
    Ich hatte wirklich Jahre nicht mehr mit C++ zu tun, da ich unter Java "unterwegs" war.

    Habt Ihr eine Idee, wie man das Lösen kann.

    Ich würde mich über Eure Hilfe sehr freuen.

    Viele Grüße 🙂



  • Templates und eigenständige Übersetzungseinheiten vertragen sich nicht besonders gut - der Compiler will bei Verwendung des Templates die komplette Definition sehen, damit er weiß, wie er daraus Code erzeugen soll. Die Lösung besteht darin, die Funktionen direkt im Header zu definieren (alternativ in einer IMPL-Datei, die am Ende des Headers eingebunden wird).



  • @CStoll

    Vielen Dank für Deine Antwort 🙂
    Das war tatsächlich die Lösung.

    Ich habe jetzt auf die Schnelle in der Maindatei die CSVDocument.cpp eingebunden. Wie funktioniert das mit der impl-Datei? Ist das eine cpp mit dem Suffix *.impl? Ist das eine gängige Konvention?



  • Wie die Dateien heißen, die du einbindest ist dem Compiler (bzw. Präprozessor) egal, allerdings ist CPP in den meisten Entwicklungsumgebungen für eine eigenständige Quelldatei reserviert (d.h. sie wird versuchen, sie direkt in den Compiler zu füttern). Deshalb verwendet man für solche Hilfsdateien wie in deinem Beispiel eine andere Datei-Endung (IMPL wie "Implementation" klingt da recht passend).



  • Falls dein Compiler C++11 (zumindest teilweise) unterstützt, könntest du die Templates auch als extern deklarieren:

    template<typename T>
    extern void foo();
    


  • Wenn Methoden nicht gefunden werden, immer erst unter dem stack nachschauen. 🤡



  • cooky451 schrieb:

    Falls dein Compiler C++11 (zumindest teilweise) unterstützt, könntest du die Templates auch als extern deklarieren:

    template<typename T>
    extern void foo();
    

    Erzähl doch nicht so einen Quatsch!



  • wird extern nicht nur vom comeau compiler unterstützt?!?
    und das auch nicht so ganz zufriedenstellend?



  • krümelkacker hat natürlich recht, das war Quatsch. Entschuldigt.



  • @Skym0sh0: Du hast extern mit export verwechselt.



  • cooky451 schrieb:

    Falls dein Compiler C++11 (zumindest teilweise) unterstützt, könntest du die Templates auch als extern deklarieren:

    template<typename T>
    extern void foo();
    

    export statt extern.

    Trotzdem hätte es linu(x)bie nichts geholfen.
    Der Comeau und der Intel Compiler sind die einzigen Compiler, die das exporten von Templates beherrschen.



  • Wusste gar nicht, dass der ICC das auch kann. export ist seit C++11 übrigens kein Standard mehr.



  • dot schrieb:

    Wusste gar nicht, dass der ICC das auch kann.

    http://software.intel.com/en-us/articles/intel-c-compiler-ansi-cc-compliance/ schrieb:

    The export keyword for templates is supported in Intel® C++ Compiler for Linux* 8.1 or newer. It is supported in the Intel® C++ Compiler for Mac OS*.

    But the export keyword for templates is not supported in the Intel® C++ Compiler for Windows or the Intel Parallel Composer.

    dot schrieb:

    export ist seit C++11 übrigens kein Standard mehr.

    Gut zu wissen...!


Anmelden zum Antworten