xtensor-stack / xtensor

C++ tensors with broadcasting and lazy computing
BSD 3-Clause "New" or "Revised" License
3.32k stars 394 forks source link

Calling `xt::view` with a const `xt::range` argument fails to compile. #2724

Open yrjo-easics opened 1 year ago

yrjo-easics commented 1 year ago

The following code to create a view using a constant range argument fails to compile:

auto tensor = xt::xarray<int>::from_shape({32, 32});
auto const span = xt::range(0, 10);
auto view = xt::view(tensor, span, xt::all());

It fails on both gcc 13.2 and clang 16.0.0

Error message (gcc):

/opt/compiler-explorer/libs/xtensor/trunk/include/xtensor/xview.hpp: In instantiation of 'xt::xview<CT, S>::xview(std::false_type, CTA&&, FSL&&, SL&& ...) [with CTA = xt::xarray_container<xt::uvector<int, std::allocator<int> >, xt::layout_type::row_major, xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xt::xtensor_expression_tag>&; FSL = xt::xrange<long int>; SL = {xt::xall<long unsigned int>}; CT = xt::xarray_container<xt::uvector<int, std::allocator<int> >, xt::layout_type::row_major, xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xt::xtensor_expression_tag>&; S = {const xt::xrange_adaptor<long int, long int, xt::placeholders::xtuph>, xt::xall<long unsigned int>}; std::false_type = std::integral_constant<bool, false>]':
/opt/compiler-explorer/libs/xtensor/trunk/include/xtensor/xview.hpp:887:9:   required from 'xt::xview<CT, S>::xview(CTA&&, FSL&&, SL&& ...) [with CTA = xt::xarray_container<xt::uvector<int, std::allocator<int> >, xt::layout_type::row_major, xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xt::xtensor_expression_tag>&; FSL = xt::xrange<long int>; SL = {xt::xall<long unsigned int>}; CT = xt::xarray_container<xt::uvector<int, std::allocator<int> >, xt::layout_type::row_major, xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xt::xtensor_expression_tag>&; S = {const xt::xrange_adaptor<long int, long int, xt::placeholders::xtuph>, xt::xall<long unsigned int>}]'
/opt/compiler-explorer/libs/xtensor/trunk/include/xtensor/xview.hpp:1813:20:   required from 'auto xt::detail::make_view_impl(E&&, std::index_sequence<__indices ...>, S&& ...) [with E = xt::xarray_container<xt::uvector<int, std::allocator<int> >, xt::layout_type::row_major, xt::svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xt::xtensor_expression_tag>&; long unsigned int ...I = {0, 1}; S = {const xt::xrange_adaptor<long int, long int, xt::placeholders::xtuph>&, xt::xall_tag}; std::index_sequence<__indices ...> = std::integer_sequence<long unsigned int, 0, 1>]'
/opt/compiler-explorer/libs/xtensor/trunk/include/xtensor/xview.hpp:1836:38:   required from 'auto xt::view(E&&, S&& ...) [with E = xarray_container<uvector<int, std::allocator<int> >, xt::layout_type::row_major, svector<long unsigned int, 4, std::allocator<long unsigned int>, true>, xtensor_expression_tag>&; S = {const xrange_adaptor<long int, long int, placeholders::xtuph>&, xall_tag}]'
<source>:13:25:   required from here
/opt/compiler-explorer/libs/xtensor/trunk/include/xtensor/xview.hpp:909:11: error: no matching function for call to 'std::tuple<const xt::xrange_adaptor<long int, long int, xt::placeholders::xtuph>, xt::xall<long unsigned int> >::tuple(xt::xrange<long int>, xt::xall<long unsigned int>)'
  909 |         , m_slices(std::forward<FSL>(first_slice), std::forward<SL>(slices)...)
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/uses_allocator_args.h:38,
                 from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/memory_resource.h:41,
                 from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/vector:80,
                 from /opt/compiler-explorer/libs/xtl/trunk/include/xtl/xsequence.hpp:17,
                 from /opt/compiler-explorer/libs/xtensor/trunk/include/xtensor/xarray.hpp:17,
                 from <source>:1:

The code fragment compiles just fine when using auto span = ... instead of auto const span = .... Maybe I am missing something here, but I assume the intended behaviour is for it to also work with const arguments?

Link to a complete example on compiler explorer

tdegeus commented 9 months ago

Could it be that xt::range is not yet assigned, and that your constness explicitly conflicts with this?

yrjo-easics commented 9 months ago

What exactly do you mean by not yet assigned? Are ranges also lazy, like tensor expressions?

My first guess was that it had something to do with the range type being forwarded as const.

tdegeus commented 9 months ago

Indeed, that it is lazy. This is not a part of the code that is my expertise, however, I would find it surprising that a lazy expression could be const.

yrjok commented 9 months ago

Upon further inspection I think I've found the cause of my problem: The get_slice_type typedef in xslice.hpp seems to select the wrong specialization when SL is const xrange_adapter<...> instead of xrange_adapter<...>.

This small change solved the compilation issue for me: https://github.com/yrjok/xtensor/commit/48d4c2294544b5b852e2b653bf7e3bc8bb260237

Not sure if this fits in the grand scheme of things because I am not familiar with the xtensor codebase.