From 1254ee74108c731484566b858b9dc34d2391d323 Mon Sep 17 00:00:00 2001 From: Joel Falcou Date: Thu, 30 Oct 2025 08:57:44 +0100 Subject: [PATCH] Fix rvalue handling in block See merge request oss/rotgen!46 --- include/rotgen/container/block/dynamic.hpp | 26 ++ include/rotgen/container/block/fixed.hpp | 17 ++ include/rotgen/detail/helpers.hpp | 13 +- include/rotgen/functions/extract.hpp | 281 ++++++++++++--------- 4 files changed, 207 insertions(+), 130 deletions(-) diff --git a/include/rotgen/container/block/dynamic.hpp b/include/rotgen/container/block/dynamic.hpp index 9ed70b2..504a15e 100644 --- a/include/rotgen/container/block/dynamic.hpp +++ b/include/rotgen/container/block/dynamic.hpp @@ -139,6 +139,32 @@ namespace rotgen { } + block(Ref&& r, Index i0, Index j0, Index ni, Index nj) + requires(!requires { typename Ref::rotgen_block_tag; } && !is_immutable) + : parent(r.base(), i0, j0, ni, nj) + { + } + + block(Ref&& r, Index i0, Index j0, Index ni, Index nj) + requires(requires { typename Ref::rotgen_block_tag; } && !is_immutable) + : parent(r.base(), i0, j0, ni, nj) + { + } + + block(Ref&& r, Index i0, Index j0) + requires(!requires { typename Ref::rotgen_block_tag; } && Rows != -1 && + Cols != -1 && !is_immutable) + : parent(r.base(), i0, j0, Rows, Cols) + { + } + + block(Ref&& r, Index i0, Index j0) + requires(requires { typename Ref::rotgen_block_tag; } && Rows != -1 && + Cols != -1 && !is_immutable) + : parent(r.base(), i0, j0, Rows, Cols) + { + } + block(parent const& base) : parent(base) {} bool is_contiguous_linear() const diff --git a/include/rotgen/container/block/fixed.hpp b/include/rotgen/container/block/fixed.hpp index df4d148..64016a5 100644 --- a/include/rotgen/container/block/fixed.hpp +++ b/include/rotgen/container/block/fixed.hpp @@ -133,11 +133,28 @@ namespace rotgen { } + block(Ref&& r, Index i0, Index j0, Index ni, Index nj) + requires(!is_immutable) + : parent(r.base(), i0, j0, ni, nj) + { + } + + block(Ref&& r, Index i0, Index j0) + requires(Rows != -1 && Cols != -1 && !is_immutable) + : parent(r.base(), i0, j0, Rows, Cols) + { + } + template block(block const& other) : parent(other.base()) { } + template + block(block&& other) : parent(other.base()) + { + } + template block(Eigen::MatrixBase const& other) : parent(other) { diff --git a/include/rotgen/detail/helpers.hpp b/include/rotgen/detail/helpers.hpp index f700640..17fd00c 100644 --- a/include/rotgen/detail/helpers.hpp +++ b/include/rotgen/detail/helpers.hpp @@ -11,6 +11,8 @@ #include +#define ROTGEN_FWD(...) static_cast(__VA_ARGS__) + namespace rotgen::detail { template constexpr int static_size() @@ -50,14 +52,7 @@ namespace rotgen::detail inline constexpr bool has_same_vector_size = []() { // No vector = noo size if (!(M::IsVectorAtCompileTime && N::IsVectorAtCompileTime)) return false; - // Row vectors -> same Cols - if (M::RowsAtCompileTime == 1 && N::RowsAtCompileTime == 1) - return M::ColsAtCompileTime == N::ColsAtCompileTime; - // Col vectors -> same Rows - if (M::ColsAtCompileTime == 1 && N::ColsAtCompileTime == 1) - return M::RowsAtCompileTime == N::RowsAtCompileTime; - // Mixing 1xN with Mx1 - return false; + else return static_size() == static_size(); }(); template @@ -65,7 +60,7 @@ namespace rotgen::detail std::conditional_t::is_immutable || std::is_const_v, std::add_const_t>, - std::remove_cvref_t>; + std::remove_reference_t>; template inline constexpr auto select_static = (M == -1 || N == -1) ? -1 : M; diff --git a/include/rotgen/functions/extract.hpp b/include/rotgen/functions/extract.hpp index 46d4633..73e7e4f 100644 --- a/include/rotgen/functions/extract.hpp +++ b/include/rotgen/functions/extract.hpp @@ -8,12 +8,14 @@ #pragma once #include +#include + namespace rotgen { namespace detail { template - void validate_extract([[maybe_unused]] Entity& e, + void validate_extract([[maybe_unused]] Entity const& e, [[maybe_unused]] Index i0, [[maybe_unused]] Index j0, [[maybe_unused]] Index ni, @@ -28,260 +30,297 @@ namespace rotgen //======================== EXTRACT ======================== template - auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj) + auto extract(Entity&& e, Index i0, Index j0, Index ni, Index nj) { detail::validate_extract(e, i0, j0, ni, nj); - if constexpr (requires { e.as_map(); }) - return extract(e.as_map(), i0, j0, ni, nj); - else return block>(e, i0, j0, ni, nj); + if constexpr (requires { ROTGEN_FWD(e).as_map(); }) + return extract(ROTGEN_FWD(e).as_map(), i0, j0, ni, nj); + else + return block>(ROTGEN_FWD(e), i0, j0, ni, + nj); } template requires(NI != -1 && NJ != -1) - auto extract(Entity& e, Index i0, Index j0) + auto extract(Entity&& e, Index i0, Index j0) { detail::validate_extract(e, i0, j0, NI, NJ); - if constexpr (requires { e.as_map(); }) - return extract(e.as_map(), i0, j0); - else return block, NI, NJ>(e, i0, j0); + if constexpr (requires { ROTGEN_FWD(e).as_map(); }) + return extract(ROTGEN_FWD(e).as_map(), i0, j0); + else + return block, NI, NJ>(ROTGEN_FWD(e), i0, + j0); } template requires((NI != -1) != (NJ != -1)) - auto extract(Entity& e, Index i0, Index j0, Index ni, Index nj) + auto extract(Entity&& e, Index i0, Index j0, Index ni, Index nj) { detail::validate_extract(e, i0, j0, ni, nj); - if constexpr (requires { e.as_map(); }) - return extract(e.as_map(), i0, j0, ni, nj); + if constexpr (requires { ROTGEN_FWD(e).as_map(); }) + return extract(ROTGEN_FWD(e).as_map(), i0, j0, ni, nj); else - return block, NI, NJ>(e, i0, j0, ni, nj); + return block, NI, NJ>(ROTGEN_FWD(e), i0, + j0, ni, nj); } //======================== TOP LEFT CORNER ======================== template - auto topLeftCorner(Entity& e, Index ni, Index nj) + auto topLeftCorner(Entity&& e, Index ni, Index nj) { - return extract(e, 0, 0, ni, nj); + return extract(ROTGEN_FWD(e), 0, 0, ni, nj); } template - auto topLeftCorner(Entity& e) + auto topLeftCorner(Entity&& e) { - return extract(e, 0, 0); + return extract(ROTGEN_FWD(e), 0, 0); } //======================== TOP RIGHT CORNER ======================== template - auto topRightCorner(Entity& e, Index ni, Index nj) + auto topRightCorner(Entity&& e, Index ni, Index nj) { - return extract(e, 0, e.cols() - nj, ni, nj); + return extract(ROTGEN_FWD(e), 0, e.cols() - nj, ni, nj); } template - auto topRightCorner(Entity& e) + auto topRightCorner(Entity&& e) { - return extract(e, 0, e.cols() - NJ); + return extract(ROTGEN_FWD(e), 0, e.cols() - NJ); } //======================== BOTTOM LEFT CORNER ======================== template - auto bottomLeftCorner(Entity& e, Index ni, Index nj) + auto bottomLeftCorner(Entity&& e, Index ni, Index nj) { - return extract(e, e.rows() - ni, 0, ni, nj); + return extract(ROTGEN_FWD(e), e.rows() - ni, 0, ni, nj); } template - auto bottomLeftCorner(Entity& e) + auto bottomLeftCorner(Entity&& e) { - return extract(e, e.rows() - NI, 0); + return extract(ROTGEN_FWD(e), e.rows() - NI, 0); } //======================== BOTTOM RIGHT CORNER ======================== template - auto bottomRightCorner(Entity& e, Index ni, Index nj) + auto bottomRightCorner(Entity&& e, Index ni, Index nj) { - return extract(e, e.rows() - ni, e.cols() - nj, ni, nj); + return extract(ROTGEN_FWD(e), e.rows() - ni, e.cols() - nj, ni, nj); } template - auto bottomRightCorner(Entity& e) + auto bottomRightCorner(Entity&& e) { - return extract(e, e.rows() - NI, e.cols() - NJ); + return extract(ROTGEN_FWD(e), e.rows() - NI, e.cols() - NJ); } //======================== TOP ROWS ======================== - template auto topRows(Entity& e, Index ni) + template auto topRows(Entity&& e, Index ni) { - if constexpr (Entity::ColsAtCompileTime == -1) - return extract(e, 0, 0, ni, e.cols()); - else return extract<-1, Entity::ColsAtCompileTime>(e, 0, 0, ni, e.cols()); + if constexpr (std::remove_cvref_t::ColsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), 0, 0, ni, e.cols()); + else + return extract<-1, std::remove_cvref_t::ColsAtCompileTime>( + ROTGEN_FWD(e), 0, 0, ni, e.cols()); } - template auto topRows(Entity& e) + template auto topRows(Entity&& e) { - if constexpr (Entity::ColsAtCompileTime == -1) - return extract(e, 0, 0, NI, e.cols()); - else return extract(e, 0, 0); + if constexpr (std::remove_cvref_t::ColsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), 0, 0, NI, e.cols()); + else + return extract::ColsAtCompileTime>( + ROTGEN_FWD(e), 0, 0); } //======================== MIDDLE ROWS ======================== template - auto middleRows(Entity& e, Index i0, Index ni) + auto middleRows(Entity&& e, Index i0, Index ni) { - if constexpr (Entity::ColsAtCompileTime == -1) - return extract(e, i0, 0, ni, e.cols()); - else return extract<-1, Entity::ColsAtCompileTime>(e, i0, 0, ni, e.cols()); + if constexpr (std::remove_cvref_t::ColsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), i0, 0, ni, e.cols()); + else + return extract<-1, std::remove_cvref_t::ColsAtCompileTime>( + ROTGEN_FWD(e), i0, 0, ni, e.cols()); } template - auto middleRows(Entity& e, Index i0) + auto middleRows(Entity&& e, Index i0) { - if constexpr (Entity::ColsAtCompileTime == -1) - return extract(e, i0, 0, NI, e.cols()); - else return extract(e, i0, 0); + if constexpr (std::remove_cvref_t::ColsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), i0, 0, NI, e.cols()); + else + return extract::ColsAtCompileTime>( + ROTGEN_FWD(e), i0, 0); } //======================== BOTTOM ROWS ======================== - template auto bottomRows(Entity& e, Index ni) + template auto bottomRows(Entity&& e, Index ni) { - if constexpr (Entity::ColsAtCompileTime == -1) - return extract(e, e.rows() - ni, 0, ni, e.cols()); + if constexpr (std::remove_cvref_t::ColsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), e.rows() - ni, 0, ni, e.cols()); else - return extract<-1, Entity::ColsAtCompileTime>(e, e.rows() - ni, 0, ni, - e.cols()); + return extract<-1, std::remove_cvref_t::ColsAtCompileTime>( + ROTGEN_FWD(e), e.rows() - ni, 0, ni, e.cols()); } - template auto bottomRows(Entity& e) + template auto bottomRows(Entity&& e) { - if constexpr (Entity::ColsAtCompileTime == -1) - return extract(e, e.rows() - NI, 0, NI, e.cols()); - else return extract(e, e.rows() - NI, 0); + if constexpr (std::remove_cvref_t::ColsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), e.rows() - NI, 0, NI, e.cols()); + else + return extract::ColsAtCompileTime>( + ROTGEN_FWD(e), e.rows() - NI, 0); } //======================== LEFT COLS ======================== - template auto leftCols(Entity& e, Index nj) + template auto leftCols(Entity&& e, Index nj) { - if constexpr (Entity::RowsAtCompileTime == -1) - return extract(e, 0, 0, e.rows(), nj); - else return extract(e, 0, 0, e.rows(), nj); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), 0, 0, e.rows(), nj); + else + return extract::RowsAtCompileTime, -1>( + ROTGEN_FWD(e), 0, 0, e.rows(), nj); } - template auto leftCols(Entity& e) + template auto leftCols(Entity&& e) { - if constexpr (Entity::RowsAtCompileTime == -1) - return extract<-1, NJ>(e, 0, 0, e.rows(), NJ); - else return extract(e, 0, 0); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == -1) + return extract<-1, NJ>(ROTGEN_FWD(e), 0, 0, e.rows(), NJ); + else + return extract::RowsAtCompileTime, NJ>( + ROTGEN_FWD(e), 0, 0); } //======================== MIDDLE COLS ======================== template - auto middleCols(Entity& e, Index j0, Index nj) + auto middleCols(Entity&& e, Index j0, Index nj) { - if constexpr (Entity::RowsAtCompileTime == -1) - return extract(e, 0, j0, e.rows(), nj); - else return extract(e, 0, j0, e.rows(), nj); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), 0, j0, e.rows(), nj); + else + return extract::RowsAtCompileTime, -1>( + ROTGEN_FWD(e), 0, j0, e.rows(), nj); } template - auto middleCols(Entity& e, Index j0) + auto middleCols(Entity&& e, Index j0) { - if constexpr (Entity::RowsAtCompileTime == -1) - return extract<-1, NJ>(e, 0, j0, e.rows(), NJ); - else return extract(e, 0, j0); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == -1) + return extract<-1, NJ>(ROTGEN_FWD(e), 0, j0, e.rows(), NJ); + else + return extract::RowsAtCompileTime, NJ>( + ROTGEN_FWD(e), 0, j0); } //======================== RIGHT COLS ======================== - template auto rightCols(Entity& e, Index nj) + template auto rightCols(Entity&& e, Index nj) { - if constexpr (Entity::RowsAtCompileTime == -1) - return extract(e, 0, e.cols() - nj, e.rows(), nj); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == -1) + return extract(ROTGEN_FWD(e), 0, e.cols() - nj, e.rows(), nj); else - return extract(e, 0, e.cols() - nj, - e.rows(), nj); + return extract::RowsAtCompileTime, -1>( + ROTGEN_FWD(e), 0, e.cols() - nj, e.rows(), nj); ; } - template auto rightCols(Entity& e) + template auto rightCols(Entity&& e) { - if constexpr (Entity::RowsAtCompileTime == -1) - return extract<-1, NJ>(e, 0, e.cols() - NJ, e.rows(), NJ); - else return extract(e, 0, e.cols() - NJ); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == -1) + return extract<-1, NJ>(ROTGEN_FWD(e), 0, e.cols() - NJ, e.rows(), NJ); + else + return extract::RowsAtCompileTime, NJ>( + ROTGEN_FWD(e), 0, e.cols() - NJ); } //======================== ROW ======================== - template auto row(Entity& e, Index i0) + template auto row(Entity&& e, Index i0) { - if constexpr (Entity::ColsAtCompileTime == -1) - return extract<1, -1>(e, i0, 0, 1, e.cols()); - else return extract<1, Entity::ColsAtCompileTime>(e, i0, 0); + if constexpr (std::remove_cvref_t::ColsAtCompileTime == -1) + return extract<1, -1>(ROTGEN_FWD(e), i0, 0, 1, e.cols()); + else + return extract<1, std::remove_cvref_t::ColsAtCompileTime>( + ROTGEN_FWD(e), i0, 0); } //======================== COL ======================== - template auto col(Entity& e, Index j0) + template auto col(Entity&& e, Index j0) { - if constexpr (Entity::RowsAtCompileTime == -1) - return extract<-1, 1>(e, 0, j0, e.rows(), 1); - else return extract(e, 0, j0); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == -1) + return extract<-1, 1>(ROTGEN_FWD(e), 0, j0, e.rows(), 1); + else + return extract::RowsAtCompileTime, 1>( + ROTGEN_FWD(e), 0, j0); } //======================== VECTOR HEAD ======================== template - auto head(Entity& e, Index n) - requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1) + auto head(Entity&& e, Index n) + requires(std::remove_cvref_t::RowsAtCompileTime == 1 || + std::remove_cvref_t::ColsAtCompileTime == 1) { - if constexpr (Entity::RowsAtCompileTime == 1) - return extract<1, Dynamic>(e, 0, 0, 1, n); - else if constexpr (Entity::ColsAtCompileTime == 1) - return extract(e, 0, 0, n, 1); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == 1) + return extract<1, Dynamic>(ROTGEN_FWD(e), 0, 0, 1, n); + else if constexpr (std::remove_cvref_t::ColsAtCompileTime == 1) + return extract(ROTGEN_FWD(e), 0, 0, n, 1); } template - auto head(Entity& e) - requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1) + auto head(Entity&& e) + requires(std::remove_cvref_t::RowsAtCompileTime == 1 || + std::remove_cvref_t::ColsAtCompileTime == 1) { - if constexpr (Entity::RowsAtCompileTime == 1) return extract<1, N>(e, 0, 0); - else if constexpr (Entity::ColsAtCompileTime == 1) - return extract(e, 0, 0); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == 1) + return extract<1, N>(ROTGEN_FWD(e), 0, 0); + else if constexpr (std::remove_cvref_t::ColsAtCompileTime == 1) + return extract(ROTGEN_FWD(e), 0, 0); } //======================== VECTOR TAIL ======================== template - auto tail(Entity& e, Index n) - requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1) + auto tail(Entity&& e, Index n) + requires(std::remove_cvref_t::RowsAtCompileTime == 1 || + std::remove_cvref_t::ColsAtCompileTime == 1) { - if constexpr (Entity::RowsAtCompileTime == 1) - return extract<1, Dynamic>(e, 0, e.cols() - n, 1, n); - else if constexpr (Entity::ColsAtCompileTime == 1) - return extract(e, e.rows() - n, 0, n, 1); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == 1) + return extract<1, Dynamic>(ROTGEN_FWD(e), 0, e.cols() - n, 1, n); + else if constexpr (std::remove_cvref_t::ColsAtCompileTime == 1) + return extract(ROTGEN_FWD(e), e.rows() - n, 0, n, 1); } template - auto tail(Entity& e) - requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1) + auto tail(Entity&& e) + requires(std::remove_cvref_t::RowsAtCompileTime == 1 || + std::remove_cvref_t::ColsAtCompileTime == 1) { - if constexpr (Entity::RowsAtCompileTime == 1) - return extract<1, N>(e, 0, e.cols() - N); - else if constexpr (Entity::ColsAtCompileTime == 1) - return extract(e, e.rows() - N, 0); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == 1) + return extract<1, N>(ROTGEN_FWD(e), 0, e.cols() - N); + else if constexpr (std::remove_cvref_t::ColsAtCompileTime == 1) + return extract(ROTGEN_FWD(e), e.rows() - N, 0); } //======================== VECTOR SEGMENT ======================== template - auto segment(Entity& e, Index s, Index n) - requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1) + auto segment(Entity&& e, Index s, Index n) + requires(std::remove_cvref_t::RowsAtCompileTime == 1 || + std::remove_cvref_t::ColsAtCompileTime == 1) { - if constexpr (Entity::RowsAtCompileTime == 1) - return extract<1, Dynamic>(e, 0, s, 1, n); - else if constexpr (Entity::ColsAtCompileTime == 1) - return extract(e, s, 0, n, 1); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == 1) + return extract<1, Dynamic>(ROTGEN_FWD(e), 0, s, 1, n); + else if constexpr (std::remove_cvref_t::ColsAtCompileTime == 1) + return extract(ROTGEN_FWD(e), s, 0, n, 1); } template - auto segment(Entity& e, Index s) - requires(Entity::RowsAtCompileTime == 1 || Entity::ColsAtCompileTime == 1) + auto segment(Entity&& e, Index s) + requires(std::remove_cvref_t::RowsAtCompileTime == 1 || + std::remove_cvref_t::ColsAtCompileTime == 1) { - if constexpr (Entity::RowsAtCompileTime == 1) return extract<1, N>(e, 0, s); - else if constexpr (Entity::ColsAtCompileTime == 1) - return extract(e, s, 0); + if constexpr (std::remove_cvref_t::RowsAtCompileTime == 1) + return extract<1, N>(ROTGEN_FWD(e), 0, s); + else if constexpr (std::remove_cvref_t::ColsAtCompileTime == 1) + return extract(ROTGEN_FWD(e), s, 0); } }