diff --git a/include/xtensor/xmath.hpp b/include/xtensor/xmath.hpp index 836e864bd..d0b5a624f 100644 --- a/include/xtensor/xmath.hpp +++ b/include/xtensor/xmath.hpp @@ -22,6 +22,7 @@ #include #include +#include #include "xaccumulator.hpp" #include "xeval.hpp" @@ -2108,7 +2109,13 @@ namespace detail { auto inner_mean = eval(mean(sc, std::move(axes_copy), evaluation_strategy::immediate)); // fake keep_dims = 1 - auto keep_dim_shape = e.shape(); + // Since the inner_shape might have a reference semantic (e.g. xbuffer_adaptor in bindings) + // We need to map it to another type before modifying it. + // We pragmatically abuse `get_strides_t` + using tmp_shape_t = get_strides_t::shape_type>; + tmp_shape_t keep_dim_shape = xtl::forward_sequence( + e.shape() + ); for (const auto& el : axes) { keep_dim_shape[el] = 1u; @@ -2712,7 +2719,13 @@ namespace detail { auto inner_mean = nanmean(sc, std::move(axes_copy)); // fake keep_dims = 1 - auto keep_dim_shape = e.shape(); + // Since the inner_shape might have a reference semantic (e.g. xbuffer_adaptor in bindings) + // We need to map it to another type before modifying it. + // We pragmatically abuse `get_strides_t` + using tmp_shape_t = get_strides_t::shape_type>; + tmp_shape_t keep_dim_shape = xtl::forward_sequence( + e.shape() + ); for (const auto& el : axes) { keep_dim_shape[el] = 1; diff --git a/include/xtensor/xutils.hpp b/include/xtensor/xutils.hpp index f09a26f1a..2b9f439ee 100644 --- a/include/xtensor/xutils.hpp +++ b/include/xtensor/xutils.hpp @@ -858,6 +858,22 @@ namespace xt using type = std::array; }; + template + class xbuffer_adaptor; + + template + struct get_strides_type> + { + // In bindings this mapping is called by reshape_view with an inner shape of type + // xbuffer_adaptor. + // Since we cannot create a buffer adaptor holding data, we map it to an std::vector. + using type = std::vector< + typename xbuffer_adaptor::value_type, + typename xbuffer_adaptor::allocator_type + >; + }; + + template using get_strides_t = typename get_strides_type::type;