请参阅下面的演示代码:
b.hpp:
#ifndef B_HPP
#define B_HPP
namespace debug {
class test {
public:
template <class T> void foo(T a);
private:
int a;
};
}
#endif
b.cpp:
#include <iostream>
#include "b.hpp"
namespace debug {
template <class T>
void test::foo(T a) {
std::cout << "debug" << std::endl;
}
}
testb.cpp:
include "b.hpp"
int main(int agrc, char *argv[])
{
debug::test a;
int c = 5;
a.foo(c);
return 0;
}
我用
编译它g++ -std=c++11 testb.cpp b.cpp'
并收到错误:
/tmp/ccnjR5S4.o: In function `main':
testb.cpp:(.text+0x1c): undefined reference to `void debug::test::foo<int>(int)'
collect2: error: ld returned 1 exit status
有什么问题?
如果我把main函数放在b.cpp中并编译b.cpp,那没关系。为什么呢?
谢谢!
答案 0 :(得分:2)
这是您需要显式实例化或将代码移回b.hpp
的情况之一。这是因为编译debug::test::foo
时testb.cpp
的实现不可见,并且编译器在编译b.cpp
时无法知道可能需要什么。
要明确实例化debug::test::foo<int>
,请将以下行添加到b.cpp
:
#include <iostream>
#include "b.hpp"
namespace debug {
template <class T>
void test::foo(T a) {
std::cout << "debug" << std::endl;
}
// Explicitly instantiate test::foo<int>
template void test::foo<int>(int); // <-- add this line
}
或者,如果您不知道此模板可能实例化的所有方式,请将其定义移回标头中的类定义。丑陋,但它会起作用。
有些编译器会进行交叉编译单元模板实例化,但正如您所发现的那样,g ++不是其中之一。 (至少,不是在我的系统上配置它。)
编辑:正如@juanchopanza上面指出的那样,这个帖子很好地解释了发生了什么:Why can templates only be implemented in the header file?