当与字符串一起使用时,函数模板出现未定义的引用错误 (GCC)

4
我需要在C++中编写一个模板函数replace_all,它将接受字符串、宽字符串、glibmm::ustring等,并将subject中所有出现的search替换为replacereplace_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

但是当我在test.cc中取消注释#include "replace_all.cc"并以这种方式编译时:
g++ -W -Wall test.cc

该程序链接并生成预期输出:
damn bar fee boor damn bardamn b

为什么链接失败,我该如何使其正常工作?
2个回答

9

由于编译器不知道在使用(实例化)模板之前要生成哪些代码,因此您无法将模板链接起来。

如果您知道将要使用哪些类型或知道它们是有限的,则可以“请求”编译器实例化模板。
如果需要,请将以下内容添加到您的.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 );

7
编译器需要在实例化时看到模板定义,否则无法生成针对您实例化模板的类型专门化的代码。正确的方法是将模板函数的实现放在头文件中,或者像您所做的那样#include .cc文件。请参考这里

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接