diff --git a/stan/math/prim/meta/holder.hpp b/stan/math/prim/meta/holder.hpp index 130ecf6b22d..8ee9d6984ff 100644 --- a/stan/math/prim/meta/holder.hpp +++ b/stan/math/prim/meta/holder.hpp @@ -479,9 +479,13 @@ inline auto make_holder_impl(F&& func, std::index_sequence, template >*> inline auto make_holder(F&& func, Args&&... args) { - return internal::make_holder_impl(std::forward(func), - std::make_index_sequence(), - std::forward(args)...); + if constexpr (is_var_matrix_v>) { + return std::forward(func)(std::forward(args)...); + } else { + return internal::make_holder_impl( + std::forward(func), std::make_index_sequence(), + std::forward(args)...); + } } /** diff --git a/stan/math/prim/meta/is_var_matrix.hpp b/stan/math/prim/meta/is_var_matrix.hpp index dbdafb67674..4cff3d132fd 100644 --- a/stan/math/prim/meta/is_var_matrix.hpp +++ b/stan/math/prim/meta/is_var_matrix.hpp @@ -19,6 +19,8 @@ struct is_var_matrix : bool_constant< math::conjunction, is_eigen>>::value> {}; +template +inline constexpr bool is_var_matrix_v = is_var_matrix>::value; /*! \ingroup require_eigens_types */ /*! \defgroup var_matrix_types var_matrix */ /*! \addtogroup var_matrix_types */ diff --git a/test/unit/math/rev/fun/transpose_test.cpp b/test/unit/math/rev/fun/transpose_test.cpp new file mode 100644 index 00000000000..8c72b89410d --- /dev/null +++ b/test/unit/math/rev/fun/transpose_test.cpp @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +// Reproduces a compile error: calling `transpose` on a `var_value` that holds +// a non-plain Eigen expression (e.g. a row/block of a `var_value` matrix). The +// resulting `var_value>` is not a plain type, so +// `make_holder` tries to wrap the `var_value` in an Eigen `Holder` expression, +// which fails because `var_value` has no `StorageKind`. +TEST_F(AgradRev, RevMatrix_transpose_var_block) { + using stan::math::transpose; + using stan::math::var_value; + + Eigen::MatrixXd m(2, 3); + m << 1, 2, 3, 4, 5, 6; + var_value m_vv(m); + + // m_vv.row(0) is a var_value>> + auto rt = transpose(m_vv.row(0)); + + EXPECT_EQ(3, rt.rows()); + EXPECT_EQ(1, rt.cols()); + EXPECT_FLOAT_EQ(1, rt.val()(0)); + EXPECT_FLOAT_EQ(2, rt.val()(1)); + EXPECT_FLOAT_EQ(3, rt.val()(2)); +}