Неопределенная ссылка на шаблон функции при использовании со строкой (GCC) - PullRequest
3 голосов
/ 05 марта 2009

Мне нужно написать шаблонную функцию replace_all в C ++, которая будет принимать строку, wstring, glibmm :: ustring и т. Д. И заменять все вхождения search в subject на 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;
}

Когда я пытаюсь скомпилировать это с помощью gcc 4.1.2

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

Я получаю:

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

Но когда я раскомментирую #include "replace_all.cc" в test.cc и скомпилирую так:

g++ -W -Wall test.cc

Программа связывает и выдает ожидаемый результат:

damn bar fee boor damn bardamn b

Почему не удается установить связь и что я могу сделать, чтобы она работала?

Ответы [ 2 ]

8 голосов
/ 05 марта 2009

Вы не можете связать шаблоны, так как компилятор не знает, какой код генерировать, прежде чем кто-то попытается использовать (создать) шаблоны.

Вы можете «попросить» компилятор создать экземпляр шаблона, если вы знаете, какие типы вы собираетесь использовать, или если вы знаете, что они ограничены.
Если хотите - поместите это в свой файл .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 );
6 голосов
/ 05 марта 2009

Компилятор должен видеть определение шаблона в момент его создания, иначе код, специализированный для типа, с которым вы создаете экземпляр шаблона, не может быть сгенерирован. Правильный способ - поместить реализацию шаблонных функций в заголовочный файл или #include .cc , как вы сделали.

...