Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing both 2D array and vector of vectors to the template function

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)

like image 437
manull Avatar asked Sep 02 '25 10:09

manull


1 Answers

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.

like image 150
Sam Varshavchik Avatar answered Sep 04 '25 01:09

Sam Varshavchik