[英]What is the proper way to define a templated class's member function when behavior is identical for template types?
弄清楚是否有东西坏了,我就把它弄坏了,我决定专门研究一个我拥有的类,以便可以自动在float和double precision之间建立模板。
我有以下[简化]类声明:
// Quatcam.h
#pragma once
#include <boost/math/quaternion.hpp>
#include <boost/numeric/ublas/matrix.hpp>
template<typename FloatType>
class QuaternionCamera
{
public:
QuaternionCamera();
void applyTranslation(boost::numeric::ublas::vector<FloatType> translationVector);
boost::numeric::ublas::matrix<FloatType> getTranslationMatrix();
protected:
boost::numeric::ublas::vector<FloatType> m_location;
boost::math::quaternion<FloatType> m_orientation;
};
我已经在.cpp文件中定义了成员函数:
//Quatcam.cpp
#include "Quatcam.h"
using namespace boost::numeric::ublas;
template<typename FloatType>
QuaternionCamera<FloatType>::QuaternionCamera()
: m_location(3),
m_orientation(1,0,0,0)
{
m_location[0] = m_location[1] = m_location[2] = 0;
}
template<typename FloatType>
void QuaternionCamera<FloatType>::applyTranslation(boost::numeric::ublas::vector<FloatType> translationVector)
{
m_location += translationVector;
}
template<typename FloatType>
boost::numeric::ublas::matrix<FloatType> QuaternionCamera<FloatType>::getTranslationMatrix()
{
boost::numeric::ublas::matrix<FloatType> returnMatrix = boost::numeric::ublas::identity_matrix<FloatType>(4,4);
boost::numeric::ublas::vector<FloatType> invTrans = -m_location;
returnMatrix(3,0) = invTrans[0];
returnMatrix(3,1) = invTrans[1];
returnMatrix(3,2) = invTrans[2];
return returnMatrix;
}
该代码本身将很高兴地编译为.lib或.obj文件,但是尝试原位使用该类会导致链接器错误。 这是我的示例main.cpp尝试使用该类:
#include "Quatcam.h"
#include <boost/numeric/ublas/io.hpp>
#include <iostream>
int main(int argc, char** argv)
{
QuaternionCamera<float> qcam;
boost::numeric::ublas::vector<float> loc(3);
loc[0] = 0;
loc[1] = 5;
loc[2] = 0;
qcam.applyTranslation(loc);
boost::numeric::ublas::matrix<float> qtm = qcam.getTranslationMatrix();
std::cout << "qtm: "<< qtm << std::endl;
return 0;
}
此代码无法链接,提示缺少getTranslationMatrix和applyTranslation符号的错误。 我认为这是因为我在技术上还没有为float类型指定功能的完全专业化。
问题
假定对于任何原子输入类型(浮点,双精度,甚至整数等),行为都是相同的,并且仅影响答案的精度。
有没有一种方法可以强制编译器不必为它们全部发出专门化的代码;
推荐链接
推荐做法
而不是从在.cpp到头部移动的定义,重命名的.cpp到.tpp和添加#include "Quatcam.tpp"
在Quatcam.h的末尾。
这是通常拆分模板声明及其定义的方式,同时仍具有可用于实例化的定义。
注意 :如果您遵循这条道路,则不应像使用.cpp
一样自行编译.tpp
。
显式实例化
您可以在.cpp中显式实例化有问题的模板,以将其提供给链接器,但这需要您知道需要实例化的确切类型。
这意味着,如果仅显式实例化QuaternionCamera<float>
,则在main.cpp尝试使用QuaternionCamera<double>
,仍然会出现链接器错误。
无法强制实例化所有“原子输入类型” ,您必须将它们全部显式写出。
template class QuaternionCamera<float>; // explicit instantiation
template class QuaternionCamera<double>; // etc, etc...
您应该将这些函数放在头文件中,而不是.cpp源文件中。
模板参数推导完成后,编译器才创建函数实例化。 生成的目标文件将包含与模板一起使用的每种类型的已编译函数。
但是,.cpp文件是单独编译的。 因此,当您编译Quatcam.cpp时,编译器找不到该类型的任何实例,也不会创建函数体。 这就是为什么您最终遇到链接器错误的原因。
简而言之,这是标题的外观:
template<typename T>
class Foo {
void Print();
T data;
};
// If template arguments are specified, function body goes to .cpp
template<>
void Foo<float>::Print();
// Template arguments are incomplete, function body should remain in the header
template<typename T>
void Foo<T>::Print() {
std::cout << data;
}
而这应该到.cpp源:
template<>
void Foo<float>::Print() {
std::cout << floor(data);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.