[英]Friend function in template class
我试图使乘法运算符成为名为TVector3的模板类的朋友。 我读过我可以在类声明中声明它之前先声明它的朋友功能,但是我这样做是徒劳的。 我知道我可以简单地定义好友函数而不是声明它,但是我希望它与正向声明技术一起使用。
特别是我正在尝试针对我的案例实施此解决方案。 我也发现这篇文章也是David Rodriguez提供了解决方案(第三版),但我不知道我做错了什么。
我使用' g ++ template.cpp tempmain.cpp a '进行编译,编译器(g ++)出现以下错误:
未定义引用'ray :: TVector3 ray :: operator *(float,ray :: TVector3 const&)'
对于以下代码:
template.h:
#ifndef TVECTOR_H
#define TVECTOR_H
#include <cmath>
namespace ray
{
//forward declarations
template <class T> class TVector3;
template <class T> TVector3<T> operator* (T, const TVector3<T> &);
template <class T>
class TVector3 {
public:
union {
struct {
T x, y, z;
};
T xyz[3];
};
//function needed
friend TVector3<T> operator*<T> (T, const TVector3<T> &);
};
}
#endif
template.cpp:
#include "template.h"
using namespace ray;
//friend operator function
template<class T> TVector3<T> operator * (T f, const TVector3<T> &v)
{
return TVector3<T>(f * v.x, f * v.y, f * v.z);
}
//instantiate template of type float
template class TVector3<float>;
tempmain.cpp:
#include <iostream>
#include "template.h"
int main()
{
ray::TVector3<float> v1, v2;
v2.x = 3;
v1 = 4.0f * v2; //this reports as undefined
std::cout << v1.x << "\n";
return 0;
}
那是完整的源代码。 我究竟做错了什么?
作为一般的经验法则,应该在标题中定义模板。 如果在cpp文件中定义它们,则需要手动实例化模板。 您正在为类模板执行此operator*
,但未实例化operator*
模板。
template TVector3<T> operator*<T> (T, const TVector3<T> &);
另外,我建议您不要使用模板operator*
,而是通过在类模板中声明和定义它来使用非模板自由函数:
template <class T>
class TVector3 {
//function needed
friend TVector3<T> operator*(T f, const TVector3<T> & v) {
return TVector3<T>(f * v.x, f * v.y, f * v.z);
}
};
这具有以下优点:自由函数(允许在第一个参数上进行转换)和模板(它将按需生成自由函数-即无需手动提供所有实现)以及可见性有限(仅将可以通过ADL查找)
您应该显式实例化运算符*,它的工作方式如下
using namespace ray;
//friend operator function
template<class T> TVector3<T> ray::operator * (T f, const TVector3<T> &v)
{
return TVector3<T>(f * v.x, f * v.y, f * v.z);
}
//instantiate template of type float
template class TVector3<float>;
template TVector3<float> ray::operator*<float>( float, TVector3<float> const& );
请记住,如果您用operator*
代替ray::operator*
编译器,那么您将无法知道您的意思是ray::operator*
而且您也没有在全局名称空间中声明新的运算符!
并且不要忘记定义TVector3( T x_, T y_, T z_ )
:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.