C++ 我不知道';无法理解此链接错误

C++ 我不知道';无法理解此链接错误,c++,c++11,C++,C++11,我不理解这个链接错误。 我有两门课: #include "Vector3.h" #include "Quaternion.h" template<typename T> class Point3 final { public: constexpr Point3(const Vector3<T>& vec) : x(vec.x), y(vec.y), z(vec.z) {} constexpr operator const Vector3

我不理解这个链接错误。 我有两门课:

#include "Vector3.h"
#include "Quaternion.h"

template<typename T>
class Point3 final
{
public:
   constexpr Point3(const Vector3<T>& vec)
   : x(vec.x), y(vec.y), z(vec.z)
   {}

   constexpr operator const Vector3<T>() const
   {
      // It is the equivalent of Vector3 = Point3 - Origin
      return Vector3<T>(x, y, z);
   }

  constexpr operator Vector3<T>() const
  {
     // It is the equivalent of Vector3 = Point3 - Origin
     return Vector3<T>(x, y, z);
  }

  T x = T(0);
  T y = T(0);
  T z = T(0);

  friend Vector3<T>;
  friend Quaternion<T>;

  friend Vector3<T> operator*( const Quaternion<T>& lhs, const Vector3<T>& rhs);
  friend Vector3<T> operator*( Vector3<T> lhs, const Vector3<T>& rhs);
};

typedef Point3<Float32> Point3f;
#包括“Vector3.h”
#包括“四元数.h”
模板
第三级期末考试
{
公众:
常量表达式点3(常量向量3和向量)
:x(向量x)、y(向量y)、z(向量z)
{}
constexpr运算符const Vector3()const
{
//它相当于向量3=点3-原点
返回向量3(x,y,z);
}
constexpr运算符Vector3()常量
{
//它相当于向量3=点3-原点
返回向量3(x,y,z);
}
tx=T(0);
T y=T(0);
tz=T(0);
朋友向量3;
朋友四元数;
友元向量3运算符*(常数四元数和lhs,常数向量3和rhs);
友元向量3运算符*(向量3左侧、常量向量3和右侧);
};
类型定义点3点3F;

模板
第三类向量期末考试
{
公众:
constexpr向量3()
{}
constexpr向量3(T_x,T_y,T_z)
:x(x),y(y),z(z)
{}
tx=T(0);
T y=T(0);
tz=T(0);
};
类型定义向量3向量3F;
我还有一个四元数类。我相信细节是不相关的,但这个类有一个非成员运算符*:

 template<typename T>
 Vector3<T> operator*( const Quaternion<T>& lhs, const Vector3<T>& rhs)
 {
    // nVidia SDK implementation
    Vector3<T> qvec(lhs.x, lhs.y, lhs.z);
    Vector3<T> uv = cross(qvec, rhs) * T(2.0) * lhs.w;    //uv = qvec ^ v;
    Vector3<T> uuv = cross(qvec, uv) * T(2.0);    //uuv = qvec ^ uv;
    return rhs + uv + uuv;
 }
模板
向量3运算符*(常数四元数和lhs,常数向量3和rhs)
{
//nVidia SDK实现
向量3 qvec(lhs.x,lhs.y,lhs.z);
Vector3 uv=cross(qvec,rhs)*T(2.0)*lhs.w;//uv=qvec^v;
Vector3 uuv=cross(qvec,uv)*T(2.0);//uuv=qvec^uv;
返回rhs+uv+uuv;
}
现在这些线产生了链接错误,但为什么呢

Math::Point3<Float32> pt = -Math::Point3<Float32>::UNIT_Z;
Math::Vector3<Float32> vec = orientation_*pt; // link error here (orientation is a Quaternion<Float32>)
//Math::Vector3<Float32> vec = orientation_*Math::Vector3<Float32>(pt); // this solve the link error.
Math::point3pt=-Math::Point3::UNIT\uz;
数学::矢量3矢量=方向此处链接错误(方向为四元数)
//数学::矢量3矢量=方向*数学::矢量3(pt);//这就解决了链路错误。
这是链接错误

Undefined symbols for architecture x86_64:
  Math::operator*(Math::Quaternion<float> const&, Math::Vector3<float> const&), referenced from:
  GfxObject::Procedural::BoxGenerator::addToTriangleBuffer(GfxObject::Procedural::TriangleBuffer&) const in ProceduralBoxGenerator.o
架构x86_64的未定义符号: 数学::运算符*(数学::四元数常量&,数学::向量3常量&),引用自: ProceduralBoxGenerator.o中的GfxObject::Procedural::BoxGenerator::addtotriangelbuffer(GfxObject::Procedural::TriangleBuffer&)常量 更新

我发现有两个问题与此非常接近,但问题在于差异

在: 和


但在我的例子中,我需要在两个模板类之间转换,而不是在同一个类中转换两个实例。我希望这会有帮助

尝试确保编译器知道您的friend声明应该是模板专用化,而不是全新非模板函数的声明:

friend Vector3<T> operator* <> (const Quaternion<T>& lhs, const Vector3<T>& rhs);
friend Vector3运算符*(常数四元数和lhs,常数Vector3和rhs);

此常见错误在C++ FAQ中讨论。

< P>试着确保编译器知道你的朋友声明应该是模板特化,而不是声明一个全新的非模板函数:

friend Vector3<T> operator* <> (const Quaternion<T>& lhs, const Vector3<T>& rhs);
friend Vector3运算符*(常数四元数和lhs,常数Vector3和rhs);
< >在C++ FAQ中讨论了这个常见错误。

从A:

开始。
模板类四元数{};
模板类向量3{};
模板类第3点{
公众:
运算符Vector3()常量{return Vector3();}
友元向量3运算符*(常数四元数和lhs,常数向量3和rhs);
};
模板
向量3算子*(常数四元数和lhs,常数向量3和rhs){}
int main(){
四元数定向;
第3点pt;
Vector3 vec=方向*pt;
返回0;
}
使用gcc 4.7编译它,我得到以下结果:

x.cc:6:79:警告:友元声明'Vector3运算符*(常量四元数&,
const Vector3&)声明了一个非模板函数
[-Wnon-template-friend]
x、 抄送:6:79:注意:(如果这不是您想要的,请确保函数模板
已声明并添加到函数名后(此处)
架构x86_64的未定义符号:
“运算符*(四元数常量和向量3常量和)”,引用自:
_ccKgI7Ru.o中的主管道
这就指出了问题所在:您正在声明一个友元函数,而不是友元模板。要解决此问题,您必须做两件事:确保模板声明位于友谊线之前,并添加尖括号:

template<typename T>
Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs) { }

template<typename T> class Point3 {
public:
  operator Vector3<T>() const { return Vector3<T>(); }
  friend Vector3<T> operator*<>(const Quaternion<T>& lhs, const Vector3<T>& rhs);
};
模板
向量3算子*(常数四元数和lhs,常数向量3和rhs){}
模板类第3点{
公众:
运算符Vector3()常量{return Vector3();}
友元向量3运算符*(常数四元数和lhs,常数向量3和rhs);
};
这将使链接器错误变成编译器错误:

错误:“方向”中的“运算符*”不匹配
注:候选人为:
注:模板向量3运算符*(常数四元数&,常数向量3&)
注意:模板参数扣除/替换失败:
注意:“Point3”不是从“const Vector3”派生的
这很有意义:声明朋友是关于谁可以访问什么数据的声明;它对模板解析的自动类型转换毫无帮助。因此,我建议采取以下措施:

template<typename T> class Point3 {
public:
  operator Vector3<T>() const { return Vector3<T>(); }
  friend Vector3<T> operator*(const Quaternion<T>& lhs, const Point3& rhs) {
    return lhs * Vector3<T>(rhs);
  }
};
模板类点3{
公众:
运算符Vector3()常量{return Vector3();}
友元向量3运算符*(常数四元数和lhs,常数点3和rhs){
返回左侧*矢量3(右侧);
}
};
这声明了一个新的内联friend操作符,它将明确地执行您想要的强制转换。

从一个:

模板类四元数{};
模板类向量3{};
模板类第3点{
公众:
运算符Vector3()常量{return Vector3();}
友元向量3运算符*(常数四元数和lhs,常数向量3和rhs);
};
模板
向量3算子*(常数四元数和lhs,常数向量3和rhs){}
int main(){
四元数定向;
第3点pt;
Vector3 vec=方向*pt;
返回0;
}
使用gcc 4.7编译它,我得到以下结果:

x.cc:6:79:警告:友元声明'Vector3运算符*(常量四元数&,
const Vector3&)声明了一个非模板函数
[-Wnon-template-friend]
x、 抄送:6:79:注意:(如果这不是什么
template<typename T> class Point3 {
public:
  operator Vector3<T>() const { return Vector3<T>(); }
  friend Vector3<T> operator*(const Quaternion<T>& lhs, const Point3& rhs) {
    return lhs * Vector3<T>(rhs);
  }
};
template<typename T> class Point3 {
public:
  operator Vector3<T>() const { return Vector3<T>(); }
  friend Vector3<T> operator*( const Quaternion<T>& lhs, const Vector3<T>& rhs)
  {
    return lhs*rhs;
  }  
};