我不明白这个链接错误
I don't understand this link error
我不明白这个链接错误。我有两个类:
#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;
和
template<typename T>
class Vector3 final
{
public:
constexpr Vector3()
{}
constexpr Vector3(T _x, T _y, T _z)
: x(_x), y(_y), z(_z)
{}
T x = T(0);
T y = T(0);
T z = T(0);
};
typedef Vector3<Float32> Vector3f;
我也有一个四元数类,细节是不相关的,我相信,但这个类有一个非成员操作符*:
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;
}
现在这些行产生一个链接错误,但是为什么呢?
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.
链接错误
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
我发现了两个非常接近的问题,但问题在于差异。
:问题1和问题2
但是在我的情况下,我需要在2个模板类之间转换,而不是相同的类,而是2个实例。我希望这将帮助!
试着让编译器知道你的friend声明应该是一个模板专门化,而不是一个全新的非模板函数的声明:
friend Vector3<T> operator* <> (const Quaternion<T>& lhs, const Vector3<T>& rhs);
从SSCCE开始:
template<typename T> class Quaternion { };
template<typename T> class Vector3 { };
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);
};
template<typename T>
Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs) { }
int main() {
Quaternion<float> orientation_;
Point3<float> pt;
Vector3<float> vec = orientation_*pt;
return 0;
}
用gcc 4.7编译,我得到以下结果:
x.cc:6:79: warning: friend declaration ‘Vector3<T> operator*(const Quaternion<T>&,
const Vector3<T>&)’ declares a non-template function
[-Wnon-template-friend]
x.cc:6:79: note: (if this is not what you intended, make sure the function template
has already been declared and add <> after the function name here)
Undefined symbols for architecture x86_64:
"operator*(Quaternion<float> const&, Vector3<float> const&)", referenced from:
_main in 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);
};
这将把链接器错误转换为编译器错误:
error: no match for ‘operator*’ in ‘orientation_ * pt’
note: candidate is:
note: template<class T> Vector3<T> operator*(const Quaternion<T>&, const Vector3<T>&)
note: template argument deduction/substitution failed:
note: ‘Point3<float>’ is not derived from ‘const Vector3<T>’
这是有道理的:声明一个朋友是关于谁可以访问什么数据的声明;它对模板解析的自动类型转换没有任何帮助。所以我建议用以下方式:
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);
}
};
声明了一个新的内联友元操作符,该操作符将显式地执行您所期望的强制转换。
实际上,为了使它工作,我必须在Point类中给朋友声明的函数一个体。我想像Scott Meyers的Effective c++(第三版)中的第46条那样做。比如这个问题,林克。
关键是内部函数必须有一个函数体。所以类Point3现在变成(我已经剥离了一些无用的代码像MvG做的,谢谢。)
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;
}
};
这使得所有的编译和链接。lhsrhs将调用在Quaternion.h中定义的操作符(包含在Point3的头文件中)。
我不明白的是为什么我没有重复符号。对我来说,Point3类中的友元操作符*和Quaternion.h头文件中定义的操作符*是相同的签名,但它编译和链接。
相关文章:
- 静态数据成员的问题-修复链接错误会导致编译器错误
- Visual Studio mkl_link_tool.exe链接错误
- C++ 实现模板单例类时出现链接错误
- 使用类模板的方法链接错误
- MySQL C++连接器链接错误
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 运行 C++ 单元测试时LNK2005链接错误
- 对 CMake 中'cudaRegisterLinkedBinary'链接错误的未定义引用?
- 链接错误,包括我创建的相同头文件 - C++
- 在Embarcadero C++ Builder中生成的DLL未解决的外部链接错误
- 使用标头保护的多个定义链接错误
- 链接错误:未定义对 stdscr 和 wgetch 的引用
- 使用 Vivek 的 Vcam / 捕获源过滤器构建/链接错误
- 升压program_options中的链接错误
- 使用 g++ 预处理器进行替换会导致链接错误
- 在调试配置中编译工作正常,但发布会给出链接错误
- 相邻矩阵设置链接错误
- 包含常量变量并包含在多个文件中的标头的链接错误
- C++链接错误,我理解但无法解决
- 是什么导致macOS Mojave上的GoogleTest链接错误