2009-03-05 7 views
3

Ich brauche eine Templat-Funktion replace_all in C++ zu schreiben, die eine Zeichenfolge nehmen, wstring, glibmm :: ustring usw. und alle Vorkommen von search in subject mit replace ersetzen.undefinierte Bezugsvorlage funktionieren, wenn mit String (GCC) verwendet

replace_all.cc

template < class T > 
T replace_all(
     T const &search, 
     T const &replace, 
     T const &subject 
) { 
     T result; 

     typename T::size_type done = 0; 
     typename T::size_type pos; 
     while ((pos = subject.find(search, done)) != T::npos) { 
       result.append (subject, done, pos - done); 
       result.append (replace); 
       done = pos + search.size(); 
     } 
     result.append(subject, done, subject.max_size()); 
     return result; 
} 

test.cc

#include <iostream> 

template < class T > 
T replace_all(
     T const &search, 
     T const &replace, 
     T const &subject 
); 

// #include "replace_all.cc" 

using namespace std; 

int main() 
{ 
     string const a = "foo bar fee boor foo barfoo b"; 
     cout << replace_all<string>("foo", "damn", a) << endl; 
     return 0; 
} 

Wenn ich versuche, dies mit gcc zu kompilieren 4.1.2

g++ -W -Wall -c replace_all.cc 
g++ -W -Wall -c test.cc 
g++ test.o replace_all.o 

ich:

test.o: In function `main': 
test.cc:(.text+0x13b): undefined reference to ` 
    std::basic_string<char, std::char_traits<char>, std::allocator<char> > 
    replace_all< std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(
     std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, 
     std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, 
     std::basic_string<char, std::char_traits<char>, std::allocator<char> > const& 
    ) 
' 
collect2: ld returned 1 exit status 
Aber

wenn ich Kommentar- #include "replace_all.cc" in test.cc und kompilieren diese Weise:

g++ -W -Wall test.cc 

Die Links-Programm und produziert erwartete Ausgabe:

damn bar fee boor damn bardamn b 

Warum Verknüpfung schlägt fehl, und was kann ich tun, damit es funktioniert ?

Antwort

8

Sie können keine Vorlagen verknüpfen, da der Compiler nicht weiß, welcher Code generiert werden soll, bevor jemand versucht, Vorlagen zu verwenden (zu instanziieren).

Sie können den Compiler bitten, die Vorlage zu instanziieren, wenn Sie wissen, welche Typen Sie verwenden werden oder ob Sie wissen, dass sie begrenzt sind.
Wenn Sie möchten - setzen Sie dies zu Ihrer .cc-Datei:

template std::string replace_all(std::string const& search, 
            std::string const& replace, 
            std::string const& subject); 


template glibmm::ustring replace_all(glibmm::ustring const& search, 
             glibmm::ustring const& replace, 
             glibmm::ustring const& subject); 
6

Der Compiler muss die Schablonendefinition zum Zeitpunkt der Instantiierung sehen, sonst kann der für den Typ, mit dem Sie die Schablone instanziieren, spezialisierte Code nicht generiert werden. Der korrekte Weg ist, die Implementierung der Template-Funktionen in the header file or to #include the .cc wie Sie getan haben.