传递2D数组和向量的向量到模板函数。

huangapple go评论62阅读模式
英文:

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 &lt;typename Edge, std::size_t N, typename Visitor&gt;
void report_edges(const Edge (&amp;AdjacencyMatrix)[N][N], Visitor &amp;&amp;visitor) {
    for (size_t i = 0; i &lt; N; ++i) {
        for (size_t j = i + 1; j &lt; N; ++j) {
            if (AdjacencyMatrix[i][j] != Edge{}) {
                visitor(i, j);
                std::cout &lt;&lt; i &lt;&lt; &quot; -&lt;&quot; &lt;&lt; AdjacencyMatrix[i][j] &lt;&lt; &quot;&gt;- &quot;&lt;&lt; j &lt;&lt; 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 &lt;typename AdjacencyMatrixType, typename Visitor&gt;
void report_edges(const AdjacencyMatrixType &amp;AdjacencyMatrix, Visitor &amp;&amp;visitor)
{
	for (size_t i = 0; i &lt; std::size(AdjacencyMatrix); ++i)
	{
		for (size_t j = i + 1; j &lt; std::size(AdjacencyMatrix[i]); ++j)
		{
			typedef decltype(AdjacencyMatrix[i][j]) Edge;
			
			if (AdjacencyMatrix[i][j] != Edge{}) {
				visitor(i, j);
				std::cout &lt;&lt; i &lt;&lt; &quot; -&lt;&quot; &lt;&lt; AdjacencyMatrix[i][j] &lt;&lt; &quot;&gt;- &quot;&lt;&lt; j &lt;&lt; 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.

huangapple
  • 本文由 发表于 2023年2月19日 09:07:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75497389.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定