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:
/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.
tmpisn't anxt::xarrayit's a builder that can automatically be converted to an array. When you pass it tomodifyXArrayit tries to do this conversion (seeafter 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 tomodifyXArray, this is as simple as not usingauto:The conversion now happens when you construct
tmpand you now have a non-temporary array that you can pass tomodifyXArray