This is only a toy example, but assume I have a matrix like class
union {
std::array<T, M * N> m_x;
std::array<vector<T, M>, N> m_col;
};
and I want to access the i
th row of the matrix in the sense that I can pass begin
and end
of this row to another function. Is there any lightweight (i.e. without introducing computational overhead) construction available for that?
Imagine for example that we want to compute a matrix-times-matrix multiplication. I would like to compute the element in the i
th row and j
th column (which is an inner product) by passing the i
th row of the first and j
th column of the second matrix to std::transform(std::execution::par_unseq, ...)
.
I could use boost::counting_iterator
, for example, but I would like to stick with the standard library.
Yes, there is std::views::stride
in C++23, but no such counterpart exists in C++20.
std::array<int, 9> matrix{0, 1, 2, 3, 4, 5, 6, 7, 8};
for (int x : matrix | std::views::stride(3)) {
std::cout << x << ' ';
}
See live example at Compiler Explorer
This prints
0 3 6
However, this feature is quite new, and you need a recent compiler to use it at this moment.
It's also questionable how much could be gained in terms of readability by using std::views
for matrix multiplication, but who am I to judge? ;)
In C++20 you could use the range-v3 library to accomplish the same thing:
#include <range/v3/view/stride.hpp>
#include <array>
#include <iostream>
int main() {
std::array<int, 9> matrix{0, 1, 2, 3, 4, 5, 6, 7, 8};
for (int x : matrix | ranges::views::stride(3)) {
std::cout << x << ' ';
}
}
See live example at Compiler Explorer
The union
declaration that you have written might be a mistake. Remember that you cannot access there non-active member of a union
outside of specific special cases.
See also Is it allowed to use unions for type punning, and if not, why?
Since this question is c++20 and you may not have access to std::views::stride(3)
, you could imitate this yourself.
template <typename T, std::size_t N, std::size_t M>
struct matrix {
std::array<T, N * M> data;
std::span<T, 3> row(std::size_t i) {
return {data.begin() + i * N, data.begin() + (i + 1) * N};
}
// TODO: similarly, return a view into a column with a column() function
// this function should return something like a span, except with a stride
};
You could then iterate over the rows and columns of a matrix by iterating over m.row(i)
and m.column(j)
.