【问题标题】:C++ Partial specialization friend declaration - template Matrix classC++ 部分特化友元声明——模板矩阵类
【发布时间】:2021-06-23 09:26:30
【问题描述】:

我创建了一个矩阵类如下:

template<typename T, unsigned N, unsigned M>
class Matrix {
public:

    template <unsigned P>
    Matrix<T,N,P> operator*(const Matrix<T,M,P>& other) const {
        Matrix<T,N,P> result;

        for(auto i = 0; i < N; i++) {
            for(auto j = 0; j < P; j++) {
                for(auto k = 0; k < M; k++) {
                    result.data[i][j] += data[i][k] * other.data[k][j];
                }
            }
        }

        return result;
    }

/* ... other members ... */

private:
    std::array<std::array<T, M>, N> data;
};

我现在遇到的问题是我无法访问other.data,因为它是另一个类(其他维度)的私有成员。我尝试将operator* 声明为这样的非会员朋友:

template<typename T, unsigned N, unsigned M>
class Matrix {
public:
    template <typename Type, unsigned RowA, unsigned ColA, unsigned ColB>
    Matrix<Type, RowA, ColB> friend operator*(const Matrix<Type, RowA, ColA>& a, const Matrix<Type, RowA, ColB>& b);

/* ... */

};

template <typename Type, unsigned RowA, unsigned ColA, unsigned ColB>
Matrix<Type, RowA, ColB>  operator*(const Matrix<Type, RowA, ColA>& a, const Matrix<Type, RowA, ColB>& b) {
    Matrix<Type, RowA, ColB> result;

    for(auto i = 0; i < RowA; i++) {
        for(auto j = 0; j < ColB; j++) {
            for(auto k = 0; k < ColA; k++) {
                result.data[i][j] += a.data[i][k] * b.data[k][j];
            }
        }
    }

    return result;
}

但它不起作用 - 编译器抱怨它找不到 operator* 的有效重载。

我在这里还有哪些其他选择?解决方案是将所有具有兼容维度的矩阵声明为朋友,但这将是部分模板专业化,据我所知这是不可能的。像这样的:

template<typename T, unsigned N, unsigned M>
class Matrix {
public:
    template<typename P>
    friend class Matrix<T,P,N>;
    
    /* ... */
};

我无法更改存储数据或Matrix 模板参数的方式 - 这是我被分配的任务。

【问题讨论】:

    标签: c++ templates matrix operator-overloading


    【解决方案1】:

    我还有哪些其他选择?

    恕我直言,您最好的选择是为矩阵添加公共访问方法,如下所示

    T const & at (unsigned i, unsigned j) const // <-- read only version
     { return data[i][j]; }                     //     for const objects
    
    T & at (unsigned i, unsigned j) // <-- read and write version
     { return data[i][j]; }
    

    所以你的operator*()(外部版本)的核心变成了

    result.at(i, j) += a.at(i, k) * b.at(k, j);
    

    并且不需要声明friend 什么都没有。

    反正你外部operator*()的签名是错误的:应该是

    template <typename T, unsigned Row, unsigned Mid, unsigned Col>
    Matrix<T, Row, Col>  operator* (Matrix<T, Row, Mid> const & a,
                                    Matrix<T, Mid, Col> const & b)
    

    您使用RowA,而不是ColA,作为第二个参数中的第一个维度。

    【讨论】:

    • 这当然是最简单的方法,谢谢。我的整个作业都集中在课堂模板和朋友身上,这就是为什么我如此专注于尝试以这种方式解决它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多