遇到模板分离链接错误的具体原因可参考:模板不支持分离编译------原因以及解决方法及细谈 C++ 类模板的分离式编译:类模板究竟要不要接口与实现分离
解决方案:
- 将声明及实现写在同一个hpp文件
根据上面链接的分析,当将hpp文件包含到cpp文件中,在预处理后,cpp文件相当于包含了声明及实现,当编译的时候可直接在当前文件中实现模板实例化,不需要链接过程 - 将声明(h)与实现(hpp)分离,但包含的时候将两个文件均包含
该种方式同第一种方式
//foo.h
#ifndef FOO_H_
#define FOO_H_
#include <pcl/point_cloud.h>
template<typename PointT>
class Foo{
public:
void compute(const pcl::PointCloud<PointT>& input,
pcl::PointCloud<PointT>& output);
};
#endif
//impl/foo.hpp
#ifndef FOO_IMPL_H_
#define FOO_IMPL_H_
#include "foo.h"
#include <iostream>
template<typename PointT>
void Foo<PointT>::compute(const pcl::PointCloud<PointT>& input,
pcl::PointCloud<PointT>& output){
output=input;
std::cout<<"hello"<<std::endl;
}
#endif
// myfoo.h
#ifndef MY_FOO_H
#define MY_FOO_H
#include <foo.h>
#include <impl/foo.hpp>
#endif
// main.cpp
#include <iostream>
#include <pcl/point_types.h>
#include "myfoo.h"
using namespace std;
int main()
{
Foo<pcl::PointXY> foo;
pcl::PointCloud<pcl::PointXY> input, output;
foo.compute(input, output);
return 0;
}
- 分离编译,借助cpp文件显示实例化,这种方式需要链接及编译器支持
同上面例子,添加foo.cpp文件,并在项目中添加对foo.cpp的依赖
// foo.cpp
#include "foo.h"
#include "impl/foo.hpp"
#include <pcl/point_types.h>
template
class Foo<pcl::PointXY>;
//main.cpp
#include <iostream>
#include <pcl/point_types.h>
#include "foo.h"
using namespace std;
int main()
{
Foo<pcl::PointXY> foo;
pcl::PointCloud<pcl::PointXY> input, output;
foo.compute(input, output); // qtcreator warning
return 0;
}
需要将foo.cpp加入到项目中,让其被编译,否则仍旧会报错(未编译),
undefined reference to Foo<pcl::PointXY>::compute
add_executable(main main.cpp foo.cpp)
# add_executable(main main.cpp)