You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模板类友元重载二元运算符:链接与访问错误排查修复

模板类友元形式重载二元运算符的编译/链接问题

测试代码:

#include "matrix.hpp"

int main()
{
    using namespace MLL;
    Matrix<int, 4, 4> a({1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16});
    a+a;
    return 0;
}

变体1:链接错误原因与修复

错误原因

类内友元声明的operator+模板参数列表,与全局定义的operator+模板参数不匹配:

  • 类内友元仅声明了typename T, std::size_t other_MAX两个模板参数;
  • 全局实现的operator+包含data_t, T, n_rows, n_cols, MAX, other_MAX六个模板参数。

编译器会将两者视为完全不同的模板,导致链接时找不到对应实例的定义,触发未引用错误。另外,实现中直接修改const引用的lhs属于非法操作。

修复方法

  1. 调整类内友元声明,使其模板参数与全局operator+完全匹配:
template<typename T, typename U, std::size_t m_rows, std::size_t m_cols, std::size_t this_MAX, std::size_t other_MAX>
friend Matrix<decltype(std::declval<T>() + std::declval<U>()), m_rows, m_cols, std::min(this_MAX, other_MAX)>
operator+(Matrix<T, m_rows, m_cols, this_MAX> const& lhs, Matrix<U, m_rows, m_cols, other_MAX> const& rhs);
  1. 修改operator+实现逻辑,先复制lhs到临时对象再修改:
template<typename data_t, typename T, std::size_t n_rows, std::size_t n_cols, std::size_t MAX, std::size_t other_MAX>
Matrix<decltype(std::declval<data_t>() + std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
operator+(Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs){
    auto result = lhs;
    const std::size_t n = n_rows * n_cols;
    for(std::size_t i = 0; i < n; ++i ){
        result.m_data_list[i] += rhs.m_data_list[i];
    }
    return result;
}

变体2:编译错误原因与修复

错误原因

  1. 友元声明的第二个参数模板类型写错:将Matrix<U, ...>写成了Matrix<T, ...>,导致友元关系不匹配,无法访问私有成员m_data_list;
  2. 同样存在直接修改const引用对象的非法操作。

修复方法

  1. 修正友元声明中的第二个参数模板类型为U:
template<typename T, typename U, std::size_t m_rows, std::size_t m_cols, std::size_t this_MAX, std::size_t other_MAX>
friend Matrix<decltype(std::declval<T>() + std::declval<U>()), m_rows, m_cols, std::min(this_MAX, other_MAX)>
operator+(Matrix<T, m_rows, m_cols, this_MAX> const& lhs, Matrix<U, m_rows, m_cols, other_MAX> const& rhs);
  1. 按照变体1的修复逻辑,修改operator+的实现,避免修改const引用对象。

完整修复后的matrix.hpp代码

#include <algorithm>
#include <array>
#include <type_traits>
#include <vector>

namespace MLL{
    template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX = 256>
    class Matrix;

    template<typename data_t, typename T, std::size_t n_rows, std::size_t n_cols, std::size_t MAX, std::size_t other_MAX>
    Matrix<decltype(std::declval<data_t>() + std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
    operator+(Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs);

    template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX>
    class Matrix{
        static constexpr bool IS_STATIC = n_rows * n_cols <= MAX;
        using container_t = typename std::conditional<IS_STATIC, std::array<data_t, n_rows * n_cols>, std::vector<data_t>>::type;

        container_t m_data_list;

    public:
        Matrix(){
            if constexpr( !IS_STATIC ){
                m_data_list.resize(n_rows * n_cols);
            }
        }

        explicit Matrix(data_t default_value){
            if constexpr( IS_STATIC ){
                m_data_list.fill(default_value);
            }else{
                m_data_list.resize(n_rows * n_cols, default_value);
            }
        }

        explicit Matrix(std::initializer_list<data_t>&& value_list){
            std::copy(value_list.begin(), value_list.end(), m_data_list.begin());
        }

        Matrix(Matrix const& other)
        : m_data_list(other.m_data_list){
        }

        Matrix(Matrix&& other) noexcept
        : m_data_list(std::move(other.m_data_list)){
        }

        Matrix& operator=(Matrix const& other){
            m_data_list = other.m_data_list;
            return *this;
        }

        Matrix& operator=(Matrix&& other) noexcept{
            m_data_list = std::move(other.m_data_list);
            return *this;
        }

        // 修正后的友元声明
        template<typename T, typename U, std::size_t m_rows, std::size_t m_cols, std::size_t this_MAX, std::size_t other_MAX>
        friend Matrix<decltype(std::declval<T>() + std::declval<U>()), m_rows, m_cols, std::min(this_MAX, other_MAX)>
        operator+(Matrix<T, m_rows, m_cols, this_MAX> const& lhs, Matrix<U, m_rows, m_cols, other_MAX> const& rhs);
    };

    // 修正后的operator+实现
    template<typename data_t, typename T, std::size_t n_rows, std::size_t n_cols, std::size_t MAX, std::size_t other_MAX>
    Matrix<decltype(std::declval<data_t>() + std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
    operator+(Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs){
        auto result = lhs;
        const std::size_t n = n_rows * n_cols;
        for(std::size_t i = 0; i < n; ++i ){
            result.m_data_list[i] += rhs.m_data_list[i];
        }
        return result;
    }
}

内容的提问来源于stack exchange,提问作者infinitezero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 22:55:18