模板上的重载算术运算符导致未解决的外部错误 [英] Overloaded arithmetic operators on a template causing an unresolved external error

查看:194
本文介绍了模板上的重载算术运算符导致未解决的外部错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在 Vector4.h 中有这个类:

#pragma once

template<typename T>
class Vector4
{
public:
T X;
T Y;
T Z;
T W;

Vector4();
Vector4(T X, T Y, T Z, T W);
~Vector4();

friend Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);
};

#include "Vector4.inl"

.inl :

and in Vector4.inl:

template<typename T>
Vector4<T>::Vector4()
{
X = 0;
Y = 0;
Z = 0;
W = 0;
}

template<typename T>
Vector4<T>::Vector4(T X, T Y, T Z, T W)
{
   this->X = X;
   this->Y = Y;
   this->Z = Z;
   this->W = W;
}

template<typename T>
Vector4<T>::~Vector4()
{

}

template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r)
{
     return(Vector4<T>(l.X * r.X, l.Y * r.Y, l.Z * r.Z, l.W * r.W));
}

当我使用它在这样的地方:

And when I use it somewhere like this:

Vector4<float> a, b;
a = a * b;

它给我一个 LNK2019未解决的外部符号

推荐答案

如注释中所述,你的朋友函数声明

As stated in the comments, your friend function declaration

friend Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);

在全局命名空间中声明一个非模板函数。当您实例化 Vector4< int> ,函数

declares a non-template function in the global namespace. When you instantiate e.g. Vector4<int>, the function

Vector4<int> operator*(const Vector4<int>& l, const Vector4<int>& r)



<被声明。请注意,它不是 功能模板。 (另见[temp.friend])

is declared. Note that it's not a function template. (Also see [temp.friend])

然后您的 Vector4.inl 声明并定义函数模板



Your Vector4.inl then declares and defines a function template

template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r)



<即一个过载的前一个函数。在表达式 a * b 中,重载解析在模板版本上选择非模板 operator * .match.best] / 1)。这会导致链接器错误,因为尚未定义非模板函数。

i.e. an overload of the former function. In the expression a * b, overload resolution chooses the non-template operator* over the template version (see [over.match.best]/1). This results in a linker error, as the non-template function hasn't been defined.

愚弄自己,简短说明:

template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);

由于此运算符是一个自由函数(非成员函数),所以这两行声明一个函数模板,很像

As this operator is a free function (a non-member function), these two lines declare a function template, much like

template<typename T>
Vector4<T> wup();

另一方面,

template<typename T>
Vector4<T> Vector4<T>::operator*(const Vector4<T>& r)
{ /* ... */ }

定义类模板( Vector4 )的成员函数(非模板)。

defines a member function (non-template) of a class template (Vector4).

一个解决方案是使用前缀声明,并仅与特定的专业化:

One solution is to use forward-declarations and befriend only a specific specialization:

template<typename T>
class Vector4;

template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r);


template<typename T>
class Vector4
{
public:
    T X;
    T Y;
    T Z;
    T W;

    Vector4();
    Vector4(T X, T Y, T Z, T W);
    ~Vector4();

    // compiler knows of some function template `operator*`,
    // can name an specialization:
    // ~~~~~~~~~~~~~~~~~~~~~~~~vvv
    friend Vector4<T> operator*<T>(const Vector4<T>& l, const Vector4<T>& r);
};

template<typename T>
Vector4<T>::Vector4()
{
    X = 0;
    Y = 0;
    Z = 0;
    W = 0;
}

template<typename T>
Vector4<T>::Vector4(T X, T Y, T Z, T W)
{
   this->X = X;
   this->Y = Y;
   this->Z = Z;
   this->W = W;
}

template<typename T>
Vector4<T>::~Vector4()
{}

template<typename T>
Vector4<T> operator*(const Vector4<T>& l, const Vector4<T>& r)
{
     return(Vector4<T>(l.X * r.X, l.Y * r.Y, l.Z * r.Z, l.W * r.W));
}

int main()
{
    Vector4<float> a, b;
    a = a * b;
}

另一个解决方案是让整个 模板而不是单个专门化:

Another solution would be to friend the whole operator* template instead of a single specialization:

template<typename U>
friend Vector4<U> operator*(Vector4<U> const&, Vector4<U> const&);

这篇关于模板上的重载算术运算符导致未解决的外部错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆