/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XTENSOR_ADAPT_HPP #define XTENSOR_ADAPT_HPP #include #include #include #include #include #include "xarray.hpp" #include "xbuffer_adaptor.hpp" #include "xfixed.hpp" #include "xtensor.hpp" namespace xt { /** * @defgroup xt_xadapt Adaptors of STL-like containers */ namespace detail { template struct array_size_impl; template struct array_size_impl> { static constexpr std::size_t value = N; }; template using array_size = array_size_impl>; template struct default_allocator_for_ptr { using type = std::allocator>>>; }; template using default_allocator_for_ptr_t = typename default_allocator_for_ptr

::type; template using not_an_array = xtl::negation>; template using not_a_pointer = xtl::negation>; template using not_a_layout = xtl::negation>; } #ifndef IN_DOXYGEN /************************** * xarray_adaptor builder * **************************/ /** * Constructs an xarray_adaptor of the given stl-like container, * with the specified shape and layout. * * @ingroup xt_xadapt * @param container the container to adapt * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC, XTL_REQUIRES(detail::not_an_array>, detail::not_a_pointer)> inline xarray_adaptor, L, std::decay_t> adapt(C&& container, const SC& shape, layout_type l = L) { static_assert(!xtl::is_integral::value, "shape cannot be a integer"); using return_type = xarray_adaptor, L, std::decay_t>; return return_type(std::forward(container), shape, l); } /** * Constructs an non-owning xarray_adaptor from a pointer with the specified shape and layout. * * @ingroup xt_xadapt * @param pointer the container to adapt * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC, XTL_REQUIRES(detail::not_an_array>, std::is_pointer>)> inline auto adapt(C&& pointer, const SC& shape, layout_type l = L) { static_assert(!xtl::is_integral::value, "shape cannot be a integer"); using buffer_type = xbuffer_adaptor>; using return_type = xarray_adaptor>; std::size_t size = compute_size(shape); return return_type(buffer_type(pointer, size), shape, l); } /** * Constructs an xarray_adaptor of the given stl-like container, * with the specified shape and strides. * * @ingroup xt_xadapt * @param container the container to adapt * @param shape the shape of the xarray_adaptor * @param strides the strides of the xarray_adaptor */ template < class C, class SC, class SS, XTL_REQUIRES(detail::not_an_array>, detail::not_a_layout>)> inline xarray_adaptor, layout_type::dynamic, std::decay_t> adapt(C&& container, SC&& shape, SS&& strides) { static_assert(!xtl::is_integral>::value, "shape cannot be a integer"); using return_type = xarray_adaptor, layout_type::dynamic, std::decay_t>; return return_type( std::forward(container), xtl::forward_sequence(shape), xtl::forward_sequence(strides) ); } /** * Constructs an xarray_adaptor of the given dynamically allocated C array, * with the specified shape and layout. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class SC, class A = detail::default_allocator_for_ptr_t

, XTL_REQUIRES(detail::not_an_array>)> inline xarray_adaptor, O, A>, L, SC> adapt( P&& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A() ) { static_assert(!xtl::is_integral::value, "shape cannot be a integer"); (void) ownership; using buffer_type = xbuffer_adaptor, O, A>; using return_type = xarray_adaptor; buffer_type buf(std::forward

(pointer), size, alloc); return return_type(std::move(buf), shape, l); } /** * Constructs an xarray_adaptor of the given dynamically allocated C array, * with the specified shape and strides. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param shape the shape of the xarray_adaptor * @param strides the strides of the xarray_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template < class P, class O, class SC, class SS, class A = detail::default_allocator_for_ptr_t

, XTL_REQUIRES(detail::not_an_array>, detail::not_a_layout>)> inline xarray_adaptor, O, A>, layout_type::dynamic, std::decay_t> adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A()) { static_assert(!xtl::is_integral>::value, "shape cannot be a integer"); (void) ownership; using buffer_type = xbuffer_adaptor, O, A>; using return_type = xarray_adaptor>; buffer_type buf(std::forward

(pointer), size, alloc); return return_type( std::move(buf), xtl::forward_sequence(shape), xtl::forward_sequence(strides) ); } /** * Constructs an xarray_adaptor of the given C array allocated on the stack, with the * specified shape and layout. * * @ingroup xt_xadapt * @param c_array the C array allocated on the stack * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class T, std::size_t N, class SC, XTL_REQUIRES(detail::not_an_array>)> inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L) { return adapt(&c_array[0], N, xt::no_ownership(), shape, l); } /** * Constructs an xarray_adaptor of the given C array allocated on the stack, with the * specified shape and stirdes. * * @ingroup xt_xadapt * @param c_array the C array allocated on the stack * @param shape the shape of the xarray_adaptor * @param strides the strides of the xarray_adaptor */ template < class T, std::size_t N, class SC, class SS, XTL_REQUIRES(detail::not_an_array>, detail::not_a_layout>)> inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides) { return adapt(&c_array[0], N, xt::no_ownership(), std::forward(shape), std::forward(strides)); } /*************************** * xtensor_adaptor builder * ***************************/ /** * Constructs a 1-D xtensor_adaptor of the given stl-like container, * with the specified layout_type. * * @ingroup xt_xadapt * @param container the container to adapt * @param l the layout_type of the xtensor_adaptor */ template inline xtensor_adaptor adapt(C&& container, layout_type l = L) { const std::array::size_type, 1> shape{container.size()}; using return_type = xtensor_adaptor, 1, L>; return return_type(std::forward(container), shape, l); } /** * Constructs an xtensor_adaptor of the given stl-like container, * with the specified shape and layout_type. * * @ingroup xt_xadapt * @param container the container to adapt * @param shape the shape of the xtensor_adaptor * @param l the layout_type of the xtensor_adaptor */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC, XTL_REQUIRES(detail::is_array>, detail::not_a_pointer)> inline xtensor_adaptor::value, L> adapt(C&& container, const SC& shape, layout_type l = L) { static_assert(!xtl::is_integral::value, "shape cannot be a integer"); constexpr std::size_t N = detail::array_size::value; using return_type = xtensor_adaptor, N, L>; return return_type(std::forward(container), shape, l); } /** * Constructs an non-owning xtensor_adaptor from a pointer with the specified shape and layout. * * @ingroup xt_xadapt * @param pointer the pointer to adapt * @param shape the shape of the xtensor_adaptor * @param l the layout_type of the xtensor_adaptor */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC, XTL_REQUIRES(detail::is_array>, std::is_pointer>)> inline auto adapt(C&& pointer, const SC& shape, layout_type l = L) { static_assert(!xtl::is_integral::value, "shape cannot be a integer"); using buffer_type = xbuffer_adaptor>; constexpr std::size_t N = detail::array_size::value; using return_type = xtensor_adaptor; return return_type(buffer_type(pointer, compute_size(shape)), shape, l); } /** * Constructs an xtensor_adaptor of the given stl-like container, * with the specified shape and strides. * * @ingroup xt_xadapt * @param container the container to adapt * @param shape the shape of the xtensor_adaptor * @param strides the strides of the xtensor_adaptor */ template < class C, class SC, class SS, XTL_REQUIRES(detail::is_array>, detail::not_a_layout>)> inline xtensor_adaptor::value, layout_type::dynamic> adapt(C&& container, SC&& shape, SS&& strides) { static_assert(!xtl::is_integral>::value, "shape cannot be a integer"); constexpr std::size_t N = detail::array_size::value; using return_type = xtensor_adaptor, N, layout_type::dynamic>; return return_type( std::forward(container), xtl::forward_sequence(shape), xtl::forward_sequence(strides) ); } /** * Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array, * with the specified layout. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param l the layout_type of the xtensor_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template > inline xtensor_adaptor, O, A>, 1, L> adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A()) { (void) ownership; using buffer_type = xbuffer_adaptor, O, A>; using return_type = xtensor_adaptor; buffer_type buf(std::forward

(pointer), size, alloc); const std::array shape{size}; return return_type(std::move(buf), shape, l); } /** * Constructs an xtensor_adaptor of the given dynamically allocated C array, * with the specified shape and layout. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param shape the shape of the xtensor_adaptor * @param l the layout_type of the xtensor_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class SC, class A = detail::default_allocator_for_ptr_t

, XTL_REQUIRES(detail::is_array>)> inline xtensor_adaptor, O, A>, detail::array_size::value, L> adapt( P&& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A() ) { static_assert(!xtl::is_integral::value, "shape cannot be a integer"); (void) ownership; using buffer_type = xbuffer_adaptor, O, A>; constexpr std::size_t N = detail::array_size::value; using return_type = xtensor_adaptor; buffer_type buf(std::forward

(pointer), size, alloc); return return_type(std::move(buf), shape, l); } /** * Constructs an xtensor_adaptor of the given dynamically allocated C array, * with the specified shape and strides. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param shape the shape of the xtensor_adaptor * @param strides the strides of the xtensor_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template < class P, class O, class SC, class SS, class A = detail::default_allocator_for_ptr_t

, XTL_REQUIRES(detail::is_array>, detail::not_a_layout>)> inline xtensor_adaptor, O, A>, detail::array_size::value, layout_type::dynamic> adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A()) { static_assert(!xtl::is_integral>::value, "shape cannot be a integer"); (void) ownership; using buffer_type = xbuffer_adaptor, O, A>; constexpr std::size_t N = detail::array_size::value; using return_type = xtensor_adaptor; buffer_type buf(std::forward

(pointer), size, alloc); return return_type( std::move(buf), xtl::forward_sequence(shape), xtl::forward_sequence(strides) ); } /** * Constructs an xtensor_adaptor of the given C array allocated on the stack, with the * specified shape and layout. * * @ingroup xt_xadapt * @param c_array the C array allocated on the stack * @param shape the shape of the xarray_adaptor * @param l the layout_type of the xarray_adaptor */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class T, std::size_t N, class SC, XTL_REQUIRES(detail::is_array>)> inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L) { return adapt(&c_array[0], N, xt::no_ownership(), shape, l); } /** * Constructs an xtensor_adaptor of the given C array allocated on the stack, with the * specified shape and strides. * * @ingroup xt_xadapt * @param c_array the C array allocated on the stack * @param shape the shape of the xarray_adaptor * @param strides the strides of the xarray_adaptor */ template < class T, std::size_t N, class SC, class SS, XTL_REQUIRES(detail::is_array>, detail::not_a_layout>)> inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides) { return adapt(&c_array[0], N, xt::no_ownership(), std::forward(shape), std::forward(strides)); } /** * Constructs an non-owning xtensor_fixed_adaptor from a pointer with the * specified shape and layout. * * @ingroup xt_xadapt * @param pointer the pointer to adapt * @param shape the shape of the xtensor_fixed_adaptor */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, std::size_t... X, XTL_REQUIRES(std::is_pointer>)> inline auto adapt(C&& pointer, const fixed_shape& /*shape*/) { using buffer_type = xbuffer_adaptor>; using return_type = xfixed_adaptor, L>; return return_type(buffer_type(pointer, detail::fixed_compute_size>::value)); } template inline auto adapt(C&& ptr, const T (&shape)[N]) { using shape_type = std::array; return adapt(std::forward(ptr), xtl::forward_sequence(shape)); } #else // IN_DOXYGEN /** * Constructs: * - an xarray_adaptor if SC is not an array type * - an xtensor_adaptor if SC is an array type * * from the given stl-like container or pointer, with the specified shape and layout. * If the adaptor is built from a pointer, it does not take its ownership. * * @ingroup xt_xadapt * @param container the container or pointer to adapt * @param shape the shape of the adaptor * @param l the layout_type of the adaptor */ template inline auto adapt(C&& container, const SC& shape, layout_type l = L); /** * Constructs: * - an xarray_adaptor if SC is not an array type * - an xtensor_adaptor if SC is an array type * * from the given stl-like container with the specified shape and strides. * * @ingroup xt_xadapt * @param container the container to adapt * @param shape the shape of the adaptor * @param strides the strides of the adaptor */ template inline auto adapt(C&& container, SC&& shape, SS&& strides); /** * Constructs: * - an xarray_adaptor if SC is not an array type * - an xtensor_adaptor if SC is an array type * * of the given dynamically allocated C array, with the specified shape and layout. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param shape the shape of the adaptor * @param l the layout_type of the adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template > inline auto adapt( P&& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A() ); /** * Constructs: * - an xarray_adaptor if SC is not an array type * - an xtensor_adaptor if SC is an array type * * of the given dynamically allocated C array, with the specified shape and strides. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param shape the shape of the adaptor * @param strides the strides of the adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template > inline auto adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A()); /** * Constructs: * - an xarray_adaptor if SC is not an array type * - an xtensor_adaptor if SC is an array type * * of the given C array allocated on the stack, with the specified shape and layout. * * @ingroup xt_xadapt * @param c_array the C array allocated on the stack * @param shape the shape of the adaptor * @param l the layout_type of the adaptor */ template inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L); /** * Constructs: * - an xarray_adaptor if SC is not an array type * - an xtensor_adaptor if SC is an array type * * of the given C array allocated on the stack, with the * specified shape and strides. * * @ingroup xt_xadapt * @param c_array the C array allocated on the stack * @param shape the shape of the adaptor * @param strides the strides of the adaptor */ template inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides); /** * Constructs an non-owning xtensor_fixed_adaptor from a pointer with the * specified shape and layout. * * @ingroup xt_xadapt * @param pointer the pointer to adapt * @param shape the shape of the xtensor_fixed_adaptor */ template inline auto adapt(C&& pointer, const fixed_shape& /*shape*/); /** * Constructs a 1-D xtensor_adaptor of the given stl-like container, * with the specified layout_type. * * @ingroup xt_xadapt * @param container the container to adapt * @param l the layout_type of the xtensor_adaptor */ template inline xtensor_adaptor adapt(C&& container, layout_type l = L); /** * Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array, * with the specified layout. * * @ingroup xt_xadapt * @param pointer the pointer to the beginning of the dynamic array * @param size the size of the dynamic array * @param ownership indicates whether the adaptor takes ownership of the array. * Possible values are ``no_ownership()`` or ``acquire_ownership()`` * @param l the layout_type of the xtensor_adaptor * @param alloc the allocator used for allocating / deallocating the dynamic array */ template > inline xtensor_adaptor, O, A>, 1, L> adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A()); #endif // IN_DOXYGEN /***************************** * smart_ptr adapter builder * *****************************/ /** * Adapt a smart pointer to a typed memory block (unique_ptr or shared_ptr) * * @code{.cpp} * #include * #include * * std::shared_ptr sptr(new double[8], std::default_delete()); * sptr.get()[2] = 321.; * std::vector shape = {4, 2}; * auto xptr = adapt_smart_ptr(sptr, shape); * xptr(1, 3) = 123.; * std::cout << xptr; * @endcode * * @ingroup xt_xadapt * @param smart_ptr a smart pointer to a memory block of T[] * @param shape The desired shape * @param l The desired memory layout * * @return xarray_adaptor for memory */ template >)> auto adapt_smart_ptr(P&& smart_ptr, const SC& shape, layout_type l = L) { using buffer_adaptor = xbuffer_adaptor>; return xarray_adaptor>( buffer_adaptor(smart_ptr.get(), compute_size(shape), std::forward

(smart_ptr)), shape, l ); } /** * Adapt a smart pointer (shared_ptr or unique_ptr) * * This function allows to automatically adapt a shared or unique pointer to * a given shape and operate naturally on it. Memory will be automatically * handled by the smart pointer implementation. * * @code{.cpp} * #include * #include * * struct Buffer { * Buffer(std::vector& buf) : m_buf(buf) {} * ~Buffer() { std::cout << "deleted" << std::endl; } * std::vector m_buf; * }; * * auto data = std::vector{1,2,3,4,5,6,7,8}; * auto shared_buf = std::make_shared(data); * auto unique_buf = std::make_unique(data); * * std::cout << shared_buf.use_count() << std::endl; * { * std::vector shape = {2, 4}; * auto obj = adapt_smart_ptr(shared_buf.get()->m_buf.data(), * shape, shared_buf); * // Use count increased to 2 * std::cout << shared_buf.use_count() << std::endl; * std::cout << obj << std::endl; * } * // Use count reset to 1 * std::cout << shared_buf.use_count() << std::endl; * * { * std::vector shape = {2, 4}; * auto obj = adapt_smart_ptr(unique_buf.get()->m_buf.data(), * shape, std::move(unique_buf)); * std::cout << obj << std::endl; * } * @endcode * * @ingroup xt_xadapt * @param data_ptr A pointer to a typed data block (e.g. double*) * @param shape The desired shape * @param smart_ptr A smart pointer to move or copy, in order to manage memory * @param l The desired memory layout * * @return xarray_adaptor on the memory */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class SC, class D, XTL_REQUIRES(detail::not_an_array>, detail::not_a_layout>)> auto adapt_smart_ptr(P&& data_ptr, const SC& shape, D&& smart_ptr, layout_type l = L) { using buffer_adaptor = xbuffer_adaptor>; return xarray_adaptor>( buffer_adaptor(data_ptr, compute_size(shape), std::forward(smart_ptr)), shape, l ); } /** * Adapt a smart pointer to a typed memory block (unique_ptr or shared_ptr) * * @code{.cpp} * #include * #include * * std::shared_ptr sptr(new double[8], std::default_delete()); * sptr.get()[2] = 321.; * auto xptr = adapt_smart_ptr(sptr, {4, 2}); * xptr(1, 3) = 123.; * std::cout << xptr; * @endcode * * @ingroup xt_xadapt * @param smart_ptr a smart pointer to a memory block of T[] * @param shape The desired shape * @param l The desired memory layout * * @return xtensor_adaptor for memory */ template auto adapt_smart_ptr(P&& smart_ptr, const I (&shape)[N], layout_type l = L) { using buffer_adaptor = xbuffer_adaptor>; std::array fshape = xtl::forward_sequence, decltype(shape)>( shape ); return xtensor_adaptor( buffer_adaptor(smart_ptr.get(), compute_size(fshape), std::forward

(smart_ptr)), std::move(fshape), l ); } /** * Adapt a smart pointer (shared_ptr or unique_ptr) * * This function allows to automatically adapt a shared or unique pointer to * a given shape and operate naturally on it. Memory will be automatically * handled by the smart pointer implementation. * * @code{.cpp} * #include * #include * * struct Buffer { * Buffer(std::vector& buf) : m_buf(buf) {} * ~Buffer() { std::cout << "deleted" << std::endl; } * std::vector m_buf; * }; * * auto data = std::vector{1,2,3,4,5,6,7,8}; * auto shared_buf = std::make_shared(data); * auto unique_buf = std::make_unique(data); * * std::cout << shared_buf.use_count() << std::endl; * { * auto obj = adapt_smart_ptr(shared_buf.get()->m_buf.data(), * {2, 4}, shared_buf); * // Use count increased to 2 * std::cout << shared_buf.use_count() << std::endl; * std::cout << obj << std::endl; * } * // Use count reset to 1 * std::cout << shared_buf.use_count() << std::endl; * * { * auto obj = adapt_smart_ptr(unique_buf.get()->m_buf.data(), * {2, 4}, std::move(unique_buf)); * std::cout << obj << std::endl; * } * @endcode * * @ingroup xt_xadapt * @param data_ptr A pointer to a typed data block (e.g. double*) * @param shape The desired shape * @param smart_ptr A smart pointer to move or copy, in order to manage memory * @param l The desired memory layout * * @return xtensor_adaptor on the memory */ template < layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class I, std::size_t N, class D, XTL_REQUIRES(detail::not_a_layout>)> auto adapt_smart_ptr(P&& data_ptr, const I (&shape)[N], D&& smart_ptr, layout_type l = L) { using buffer_adaptor = xbuffer_adaptor>; std::array fshape = xtl::forward_sequence, decltype(shape)>( shape ); return xtensor_adaptor( buffer_adaptor(data_ptr, compute_size(fshape), std::forward(smart_ptr)), std::move(fshape), l ); } /** * @brief xtensor adaptor for a pointer. * * Construct for example with: * * @code{.cpp} * #include * * std::array shape = {2, 2}; * std::vector data = {1, 2, 3, 4}; * * xt::xtensor_pointer a = xt::adapt(data.data(), 4, xt::no_ownership(), shape); * @endcode * * @ingroup xt_xadapt * @tparam T The data type (e.g. ``double``). * @tparam N The number of dimensions. * @tparam L The xt::layout_type() of the xtensor. */ template using xtensor_pointer = xtensor_adaptor< xbuffer_adaptor, xt::no_ownership, detail::default_allocator_for_ptr_t>, N, L>; /** * @brief xarray adaptor for a pointer. * * Construct for example with: * * @code{.cpp} * #include * * std::vector data(4, 0); * xt::svector shape({2, 2}); * * xt::xarray_pointer a = xt::adapt(data.data(), data.size(), xt::no_ownership(), shape); * @endcode * * @ingroup xt_xadapt * @tparam T The data type (e.g. ``double``). * @tparam L The xt::layout_type() of the xarray. * @tparam SC The shape container type (e.g. ``xt::svector``). Default matches * xt::adapt(P&&, typename A::size_type, O, const SC&, layout_type, const A& alloc) */ template < class T, layout_type L = XTENSOR_DEFAULT_LAYOUT, class SC = XTENSOR_DEFAULT_SHAPE_CONTAINER(T, std::allocator, std::allocator)> using xarray_pointer = xarray_adaptor< xbuffer_adaptor, xt::no_ownership, detail::default_allocator_for_ptr_t>, L, SC>; } #endif