Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I pass an XTensor array by reference so that I can modify it in-place?

I am using the C++ library XTensor. I want to modify an array in-place in a function.

void modifyXArray(xt::xarray<double>& arr) {
    arr += 1;
}

However when using this function:

auto tmp = xt::linspace(0, 1, 100);
modifyXArray(tmp);

I get the error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

/home/tom/src/xtensor-interp/tests/test_interpolator.cpp: In member function ‘virtual void Foo_Bar_Test::TestBody()’:
/home/tom/src/xtensor-interp/tests/test_interpolator.cpp:92:18: error: cannot bind non-const lvalue reference of type ‘xt::xarray<double>&’ {aka ‘xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xt::xtensor_expression_tag>&’} to an rvalue of type ‘xt::xarray<double>’ {aka ‘xt::xarray_container<xt::uvector<double, std::allocator<double> >, xt::layout_type::row_major, xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xt::xtensor_expression_tag>’}
   92 |     modifyXArray(tmp);
      |                  ^~~
In file included from /home/tom/src/xtensor-interp/XTensorInterp/XTensorInterp/interpolator.h:11,
                 from /home/tom/src/xtensor-interp/tests/test_interpolator.cpp:1:
/home/tom/src/xtensor-interp/build/Release/_deps/xtensor-src/include/xtensor/xarray.hpp:501:12: note:   after user-defined conversion: ‘xt::xarray_container<EC, L, SC, Tag>::xarray_container(const xt::xexpression<E>&) [with E = xt::xgenerator<xt::detail::arange_generator<double, int, double>, int, std::array<long unsigned int, 1> >; EC = xt::uvector<double, std::allocator<double> >; xt::layout_type L = xt::layout_type::row_major; SC = xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>; Tag = xt::xtensor_expression_tag]’
  501 |     inline xarray_container<EC, L, SC, Tag>::xarray_container(const xexpression<E>& e)
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/tom/src/xtensor-interp/tests/test_interpolator.cpp:85:39: note:   initializing argument 1 of ‘void modifyXArray(xt::xarray<double>&)’
   85 | void modifyXArray(xt::xarray<double>& arr) {
      |                   ~~~~~~~~~~~~~~~~~~~~^~~

I can pass in an array by reference if I mark it as const, but then I cant modify it.

>Solution :

tmp isn’t an xt::xarray it’s a builder that can automatically be converted to an array. When you pass it to modifyXArray it tries to do this conversion (see after user-defined conversion: ‘xt::xarray_container... in the error message) but the conversion returns a temporary (rvalue) and you can’t bind a temporary to a non-const reference (even if you did the temporary would be thrown away and your original variable wouldn’t be modified). You need to force the conversion to an array before you pass to modifyXArray, this is as simple as not using auto:

xt::xarray<double> tmp = xt::linspace(0, 1, 100);
modifyXArray(tmp);

The conversion now happens when you construct tmp and you now have a non-temporary array that you can pass to modifyXArray

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading