模板类友元重载二元运算符:链接与访问错误排查修复
模板类友元形式重载二元运算符的编译/链接问题
测试代码:
#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属于非法操作。
修复方法
- 调整类内友元声明,使其模板参数与全局
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);
- 修改
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:编译错误原因与修复
错误原因
- 友元声明的第二个参数模板类型写错:将
Matrix<U, ...>写成了Matrix<T, ...>,导致友元关系不匹配,无法访问私有成员m_data_list; - 同样存在直接修改
const引用对象的非法操作。
修复方法
- 修正友元声明中的第二个参数模板类型为
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的修复逻辑,修改
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
相关产品推荐
相关产品推荐

