【问题标题】:Template friend function of template class模板类的模板友元功能
【发布时间】:2018-07-02 18:04:13
【问题描述】:

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

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

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

【问题讨论】:

    标签: c++ c++11 templates declaration friend


    【解决方案1】:

    您的实物不匹配。

    您的初始声明和后来的定义具有以下签名:

    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);
    

    这只有一个模板参数:TN 固定在这里。这个友元声明也声明了这个函数模板。这是一个更好的匹配,但没有实际定义,因此您看到的行为。


    我认为你有两个选择。

    1. 删除operator* 的命名空间范围声明,只在Matrix 的定义中声明和定义友元operator*

    2. 更改朋友声明以匹配命名空间范围声明:

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

    (1) 通常是更好的选择 - 不涉及将更多 operator*s 添加到全局范围内,这对编译时间有好处。

    【讨论】:

    • 第三个选项:template&lt;typename T&gt; Matrix&lt;42&gt; operator* (const Matrix&lt;42&gt; &amp;m1, const T &amp;m2) {/*..*/} 每个值 ;-)
    猜你喜欢
    • 2021-10-25
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多