Reputation: 6959
I have a matrix class with a transposedView()
method that I have been using for years as a "zero overhead" conversion between row and column vectors.
template<int M, int N=M, typename T = double>
struct mat {
std::array<T,M*N> buf;
// ...
template<int Md = M, int Nd = N, typename = std::enable_if_t<Md == 1 || Nd == 1>>
const mat<N, M, T>& transposedView() const {
static_assert(M == 1 || N == 1, "transposedView() supports only vectors, not general matrices.");
return *reinterpret_cast<const mat<N, M, T>*>(this);
}
}
I used to trust this because the memory layout of mat<1,N>
corresponds exactly to mat<N,1>
, but I have just learned that this function has Undefined Behavior. Do you have any advice on what I could replace the contents/implementation of this function with?
Upvotes: 3
Views: 441
Reputation: 13040
You can design a new view class template, like std::string_view
corresponding to std::string
, or Eigen::Map
corresponding to Eigen::Matrix
(so you can see, this is a common design in C++). The view class template may simply hold a pointer pointing to the beginning of the sequence it views and a size (if you only want to support a view for a whole matrix, you can omit the size member as it can be inferred from its template parameters). Your transposedView
function can return such a view class instead.
template<int M, int N=M, typename T = double>
struct mat_view {
T *begin;
std::size_t size;
// member functions you want to support
// ...
}
template<int M, int N=M, typename T = double>
struct mat {
std::array<T,M*N> buf;
// ...
template<int Md = M, int Nd = N, typename = std::enable_if_t<Md == 1 || Nd == 1>>
const mat_view<N, M, T> transposedView() const {
static_assert(M == 1 || N == 1, "transposedView() supports only vectors, not general matrices.");
return {std::begin(buf), M * N};
}
}
Upvotes: 1