Necesito escribir una función de plantilla replace_all en C++, que tendrá una cadena, wstring, glibmm::ustring etc. y reemplazar todas las apariciones de search en subject con replace.

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

Cuando trato de compilar esta usando gcc 4.1.2

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

Puedo obtener:

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

Pero cuando me quite el comentario de #include "replace_all.cc" en test.cc y compilar de esta manera:

g++ -W -Wall test.cc

El programa enlaces y produce el resultado esperado:

damn bar fee boor damn bardamn b

Por qué la vinculación de un error y qué puedo hacer para que funcione?

InformationsquelleAutor Tometzky | 2009-03-05

2 Comentarios

  1. 8

    No se puede vincular plantillas como compilador no sabe qué código para generar antes de que alguien intenta utilizar ( instanciar ) plantillas.

    Puede «pedir» compilador para crear una instancia de la plantilla si usted sabe que los tipos se va a utilizar o si usted sabe que ellos son limitados.

    Si usted quiere – poner esto a su .cc de archivo:

    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 );
  2. 6

    El compilador necesita para ver la definición de la plantilla en el momento de creación de instancias, de lo contrario el código especializado para el tipo que crear una instancia de la plantilla con la que no puede ser generado. La forma correcta es colocar la implementación de la plantilla de funciones en el archivo de encabezado o #include el .cc como lo hizo.

Dejar respuesta

Please enter your comment!
Please enter your name here