Domanda

Ho bisogno di scrivere una funzione templated replace_all in C ++ che prenderà una stringa, wstring, glibmm :: ustring ecc. e sostituirà tutte le occorrenze di cerca in subject con sostituisci .

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;
}

Quando provo a compilare questo usando gcc 4.1.2

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

Ottengo:

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

Ma quando decommento #include " replace_all.cc " in test.cc e compilo in questo modo:

g++ -W -Wall test.cc

Il programma collega e produce l'output previsto:

damn bar fee boor damn bardamn b

Perché il collegamento non riesce e cosa posso fare per farlo funzionare?

È stato utile?

Soluzione

Non puoi collegare modelli in quanto il compilatore non sa quale codice generare prima che qualcuno tenti di utilizzare (istanziare) i modelli.

Puoi " chiedere " compilatore per creare un'istanza del modello se sai quali tipi hai intenzione di utilizzare o se sai che sono limitati.
Se vuoi, metti questo nel tuo file .cc:

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 );

Altri suggerimenti

Il compilatore deve vedere la definizione del modello nel punto di istanza, altrimenti non è possibile generare il codice specializzato per il tipo con cui si crea un'istanza del modello. Il modo corretto è mettere l'implementazione delle funzioni del modello nell'intestazione o per #includere il .cc come hai fatto tu.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top