如何让C++模板函数同时兼容二维数组与vector<vector>参数?
问题描述
现有如下C++模板函数,用于接收二维数组形式的邻接矩阵,遍历并输出所有非默认值的边,同时调用传入的访问器:
template <typename Edge, std::size_t N, typename Visitor> void report_edges(const Edge (&AdjacencyMatrix)[N][N], Visitor &&visitor) { for (size_t i = 0; i < N; ++i) { for (size_t j = i + 1; j < N; ++j) { if (AdjacencyMatrix[i][j] != Edge{}) { visitor(i, j); std::cout << i << " -<" << AdjacencyMatrix[i][j] << ">-" << j << std::endl; } } } }
需要改写该函数,要求:
- 同一模板函数同时支持二维数组和
std::vector<std::vector<Edge>>作为输入参数 - 禁止编写外部辅助函数
尝试移除模板参数std::size_t N仅保留Edge模板时,会对二维数组类型产生编译错误,需解决此问题。
解决方案
核心思路是将矩阵类型设为通用模板参数,不再固定为二维数组,利用C标准库的std::size(C17及以上)统一获取矩阵维度——该函数对内置数组和标准容器(如vector)均有效。修改后的代码如下:
#include <vector> #include <iostream> #include <iterator> // 包含std::size template <typename Matrix, typename Visitor> void report_edges(const Matrix& adjacency_matrix, Visitor&& visitor) { using EdgeType = std::decay_t<decltype(adjacency_matrix[0][0])>; const auto size = std::size(adjacency_matrix); for (std::size_t i = 0; i < size; ++i) { // 假设邻接矩阵是方阵,若需支持非方阵可单独获取列数 const auto row_size = std::size(adjacency_matrix[i]); for (std::size_t j = i + 1; j < row_size; ++j) { if (adjacency_matrix[i][j] != EdgeType{}) { visitor(i, j); std::cout << i << " -<" << adjacency_matrix[i][j] << ">-" << j << std::endl; } } } }
代码说明
- 模板参数调整:将原有的
Edge和N合并为通用的Matrix模板参数,适配任意支持[]访问和std::size的二维容器/数组类型。 - Edge类型推导:通过
decltype(adjacency_matrix[0][0])获取元素类型,用std::decay_t去除引用和cv限定符,得到原始的边类型。 - 维度获取:
std::size(adjacency_matrix)对二维数组返回编译期常量N,对vector<vector>返回运行时的size()值,实现统一处理。 - 兼容性:无需额外函数,同一个模板即可处理两种输入类型,符合要求。
测试示例
// 测试二维数组 int arr[3][3] = { {0, 1, 0}, {0, 0, 2}, {0, 0, 0} }; // 测试vector<vector> std::vector<std::vector<int>> vec = { {0, 3, 0}, {0, 0, 4}, {0, 0, 0} }; // 简单的访问器函数 void print_visitor(std::size_t from, std::size_t to) { std::cout << "Visited edge: " << from << " -> " << to << "\n"; } int main() { std::cout << "=== Testing array ===\n"; report_edges(arr, print_visitor); std::cout << "\n=== Testing vector ===\n"; report_edges(vec, print_visitor); return 0; }
输出结果:
=== Testing array === Visited edge: 0 -> 1 0 -<1>- 1 Visited edge: 1 -> 2 1 -<2>- 2 === Testing vector === Visited edge: 0 -> 1 0 -<3>- 1 Visited edge: 1 -> 2 1 -<4>- 2
内容的提问来源于stack exchange,提问作者manull
相关产品推荐
相关产品推荐

