当前位置: 首页 > 知识库问答 >
问题:

模板类的模板友元函数

杜浩壤
2023-03-14

我想知道如果函数的模板参数包括但不限于类的模板参数,如何使函数成为类的朋友并在类外定义函数。

例如,我有以下模板类和模板朋友函数:

template<int N>  class Matrix;
template<typename T, int N> Matrix<N> operator*(const Matrix<N> &m1, const T &m2);

// class definition
template<int N>
class Matrix{
  template<typename T>
  friend Matrix<N> operator* (const Matrix<N> &m1, const T &m2);
};

// friend function definition
template<typename T, int N> Matrix<N> operator*(const Matrix<N> &m1, const T &m2)
{
    return m1; // just as an example
}

如果我编译:

Matrix<3> m;
m * 1.0;

我会得到以下链接器错误:

test.cc:(.text+0x1c7): undefined reference to `Matrix<3> operator*<double>(Matrix<3> const&, double const&)'
collect2: error: ld returned 1 exit status

共有1个答案

荆鸿畅
2023-03-14

你的种类不匹配。

您最初的声明和后来的定义有这样的签名:

template<typename T, int N>
Matrix<N> operator*(const Matrix<N> &m1, const T &m2);

这是一个采用两个模板参数的函数模板:TN

然而,在您的类中,您作为朋友创建了一个具有以下签名的函数模板:

template<typename T>
friend Matrix<N> operator* (const Matrix<N> &m1, const T &m2);

这只有一个模板参数:T. N 在这里是固定的。此友元声明还声明此函数模板。这是一个更好的匹配,但实际上没有定义,因此你看到的行为。

我认为你有两个选择。

>

  • 删除运算符*的名称空间范围声明,只需在矩阵”的定义中声明和定义友联的操作符*

    更改友元声明以匹配命名空间范围声明:

    template<typename T, int M>
    friend Matrix<M> operator* (const Matrix<M> &m1, const T &m2);
    

    (1) 通常是更好的选择-不需要在全局范围中添加更多的运算符*,这有利于编译时间。

  •  类似资料:
    • 我有一个类模板和一个函数模板定义了一个,它引用要绑定到的模板类型。 我想要的是将< code>make_obj函数声明为< code>friend,这样它可以创建< code>Obj的,但是其他人不能(除了通过copy ctor)。 我尝试了几个朋友声明,包括 和 后者是使< code>make_obj的所有模板实例化成为< code>Obj类的朋友的不太理想的尝试。然而,在这两种情况下,我得到相

    • 我正在学习一个视频教程,我想声明一个模板函数作为模板类的朋友。我不知道为什么代码会抛出错误。 编译器抛出错误。 错误: templates\u friends\u 38。cpp:在“void doSomething2(T)[T=int]”的实例化中:templates\u friends\u 38。cpp:40:19:此处需要templates\u friends\u 38。cpp:32:9:错误

    • 是否允许在友元声明中为模板参数提供默认值? Visual Studio 2015似乎允许这样做。gcc拒绝了。我在cppreference页面上找不到任何内容。

    • 我试图使乘法运算符成为名为TVector3的模板类的朋友。我读过,我可以在类声明中声明朋友函数之前,对其进行前向声明,但我这样做的尝试是徒劳的。我知道我可以简单地定义friend函数而不是声明它,但我希望它能与前向声明技术一起工作。 特别是,我试图为我的案例实施这个解决方案。我发现这篇文章也是David Rodriguez给出的解决方案(第三个版本),但我不知道我做错了什么。 我使用'g temp

    • 考虑以下示例: 使用GCC 5.2编译会引发以下编译错误: 但是标准在14.6.5中说: 友元类或函数可以在类模板中声明。当模板被实例化时,其朋友的名称被视为在实例化点显式声明了专门化。 为什么编译失败?在GCC 3.4中,通过。

    • 函数和整个类都可以声明为非模板类友元。使用类模板,可以声明各种各样的友元关系。友元可以在类模板与全局函数间、另一个类(可能是模板类)的成员函数间或整个类中(可能是模板类)建立。建立这种友元关系的符号可能很繁琐。 在下列X类的类模板中声明为: template<class T>class X 下列友元声明: friend void f1(); 使函数f1成为从上述类模板实例化的每个模板类的友元。 在