英文:
Passing both 2D array and vector of vectors to the template function
问题
我有这段代码:
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::size_t N
并只使用Edge
模板,而不使用任何大小,但也发生了错误(在典型的二维数组的情况下,这是相当明显的)。
英文:
I have this code:
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;
}
}
}
}
It accepts 2D array of edges and report them all. The question is: how to rewrite this function to take not only array of arrays, but ALSO vector of vectors as an adjacency matrix parameter? Function must have the same template i suppose. It is also prohibited to write external function, e.g. to process iterators
I've tried to remove std::size_t N
and use only Edge
template, without any sizes at all, but errors also occured (it is rather obvious in case of typical 2D array)
答案1
得分: 3
不同于数组,向量的大小在编译时是未知的,只有在运行时才知道。毕竟,这正是它们存在的唯一原因:实现在运行时已知大小的数组。
因此,在模板中尝试推断向量的大小,严格发生在编译时,总是会以失败告终。
但很幸运的是,std::size
已经为数组和向量进行了重载。因此,您可以使用 std::size
来完成繁重的工作:
template <typename AdjacencyMatrixType, typename Visitor>
void report_edges(const AdjacencyMatrixType &AdjacencyMatrix, Visitor &&visitor)
{
for (size_t i = 0; i < std::size(AdjacencyMatrix); ++i)
{
for (size_t j = i + 1; j < std::size(AdjacencyMatrix[i]); ++j)
{
typedef decltype(AdjacencyMatrix[i][j]) Edge;
if (AdjacencyMatrix[i][j] != Edge{}) {
visitor(i, j);
std::cout << i << " -<" << AdjacencyMatrix[i][j] << ">- " << j << std::endl;
}
}
}
}
唯一的其他技巧是推断 Edge
类型需要一点工作。decltype
来帮忙。
还请注意,由于向量的大小只在运行时已知,所以您有责任确保二维向量中每行的大小是正确的。
英文:
Unlike an array, the size of a vector is not known at compile time, only at runtime. After all, that's the sole reason for their existence: to implement arrays whose size is known at runtime.
So, any attempt to deduce the size of the vector in a template, which happens strictly at compile-time, will always end in tears.
But, it's very fortunate that std::size
is overloaded for both arrays and vectors. As such, you can use std::size
for the heavy lifting:
template <typename AdjacencyMatrixType, typename Visitor>
void report_edges(const AdjacencyMatrixType &AdjacencyMatrix, Visitor &&visitor)
{
for (size_t i = 0; i < std::size(AdjacencyMatrix); ++i)
{
for (size_t j = i + 1; j < std::size(AdjacencyMatrix[i]); ++j)
{
typedef decltype(AdjacencyMatrix[i][j]) Edge;
if (AdjacencyMatrix[i][j] != Edge{}) {
visitor(i, j);
std::cout << i << " -<" << AdjacencyMatrix[i][j] << ">- "<< j << std::endl;
}
}
}
}
The only other trick is that deducing the type of Edge
requires a little bit of work. decltype
to the rescue.
Also note that since the size of the vector is known only at runtime it's your responsibility to make sure that the sizes of each row in the 2D vector is correct.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论