xtensor icon indicating copy to clipboard operation
xtensor copied to clipboard

Error with xt::axis_slice_xxxx iterators for const arrays with std algorithms

Open paceholder opened this issue 2 years ago • 0 comments

Consider a simple example: we want to take a slice iterator over a sorted array and apply std::lower_bound function to it.

#include <xtensor/xarray.hpp>
#include <xtensor/xaxis_slice_iterator.hpp>
#include <xtensor/xio.hpp>

xarray<int> a = {{{1, 2, 3, 4},
                  {5, 6, 7, 8},
                  {9, 10, 11, 12}},
                 {{13, 14, 15, 16},
                  {17, 18, 19, 20},
                  {21, 22, 23, 24}}};

auto iter = axis_slice_begin(a, 0);
auto end = axis_slice_end(a, 0);
auto it = std::lower_bound(iter, end, 
                           8,
                           (auto cont & elementIt, int p)
                           {
                             return elementIt[0] < p;
                           });

 std::cout << *it << std::endl;  // PRINTS:   {13, 17, 21} 

Now if we use a const ref to our array and pass it to the same function, the code does not compile anymore:

auto const & b = a;  // const ref to the same array
auto iter = axis_slice_begin(b, 0);
auto end = axis_slice_end(b, 0);

Compiler output: (it is approximately the same for gcc on linux and clang on macos)

In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/algorithm:670:
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__algorithm/copy.h:35:19: error: cannot assign to return value because function 'operator*' returns a const value
        *__result = *__first;
        ~~~~~~~~~ ^
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__algorithm/copy.h:69:23: note: in instantiation of function template specialization 'std::__copy_constexpr<xt::xiterator<xt::xstepper<const xt::xarray_container<xt::uvector<double>, xt::layout_type::dynamic, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>, xt::xiterator<xt::xstepper<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>>' requested here
        return _VSTD::__copy_constexpr(__first, __last, __result);
                      ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xstrided_view.hpp:416:18: note: in instantiation of function template specialization 'std::copy<xt::xiterator<xt::xstepper<const xt::xarray_container<xt::uvector<double>, xt::layout_type::dynamic, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>, xt::xiterator<xt::xstepper<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>>' requested here
            std::copy(t.cbegin(), t.cend(), v.begin());
                 ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xstrided_view.hpp:424:31: note: in instantiation of function template specialization 'xt::xstrided_view_detail::run_assign_temporary_impl<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>, xt::xarray_container<xt::uvector<double>, xt::layout_type::dynamic, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>>>' requested here
        xstrided_view_detail::run_assign_temporary_impl(*this, tmp, std::integral_constant<bool, fast_assign>{});
                              ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xsemantic.hpp:662:30: note: in instantiation of member function 'xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>::assign_temporary_impl' requested here
        this->derived_cast().assign_temporary_impl(std::move(tmp));
                             ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xstrided_view.hpp:379:22: note: in instantiation of member function 'xt::xview_semantic<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>::assign_temporary' requested here
        return this->assign_temporary(std::move(tmp));
                     ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xaxis_slice_iterator.hpp:28:11: note: in instantiation of member function 'xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>::operator=' requested here
    class xaxis_slice_iterator
          ^
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__algorithm/lower_bound.h:55:19: note: in instantiation of function template specialization 'std::__lower_bound<(lambda at /Users/dmitry/projects/gamma/client/logview/CurveObject.cpp:1209:31) &, xt::xaxis_slice_iterator<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>, double>' requested here
    return _VSTD::__lower_bound<_Comp_ref>(__first, __last, __value_, __comp);
                  ^
/Users/dmitry/projects/gamma/client/logview/CurveObject.cpp:1207:19: note: in instantiation of function template specialization 'std::lower_bound<xt::xaxis_slice_iterator<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>, double, (lambda at /Users/dmitry/projects/gamma/client/logview/CurveObject.cpp:1209:31)>' requested here
  auto iit = std::lower_bound(beginIt, endIt,
                  ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xiterator.hpp:337:9: note: function 'operator*' which returns const-qualified type 'xt::xiterator<xt::xstepper<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>::reference' (aka 'const double &') declared here
        reference operator*() const;
        ^~~~~~~~~
In file included from /Users/dmitry/projects/gamma/client/logview/CurveObject.cpp:1:
In file included from /Users/dmitry/projects/gamma/client/logview/CurveObject.hpp:3:
In file included from /Users/dmitry/projects/gamma/client/logview/LogViewObject.hpp:3:
In file included from /opt/homebrew/lib/QtWidgets.framework/Headers/QGraphicsItem:1:
In file included from /opt/homebrew/lib/QtWidgets.framework/Headers/qgraphicsitem.h:8:
In file included from /opt/homebrew/lib/QtCore.framework/Headers/qobject.h:11:
In file included from /opt/homebrew/lib/QtCore.framework/Headers/qstring.h:14:
In file included from /opt/homebrew/include/QtCore/qchar.h:651:
In file included from /opt/homebrew/include/QtCore/qstringview.h:8:
In file included from /opt/homebrew/include/QtCore/qbytearray.h:11:
In file included from /opt/homebrew/include/QtCore/qarraydatapointer.h:7:
In file included from /opt/homebrew/include/QtCore/qarraydataops.h:9:
In file included from /opt/homebrew/include/QtCore/qcontainertools_impl.h:20:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/algorithm:670:
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__algorithm/copy.h:44:12: error: no matching function for call to '__copy_constexpr'
    return _VSTD::__copy_constexpr(__first, __last, __result);
           ^~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__config:858:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_ABI_NAMESPACE
              ^
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__algorithm/copy.h:72:20: note: in instantiation of function template specialization 'std::__copy<xt::xiterator<xt::xstepper<const xt::xarray_container<xt::uvector<double>, xt::layout_type::dynamic, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>, xt::xiterator<xt::xstepper<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>>' requested here
            _VSTD::__copy(_VSTD::__unwrap_iter(__first),
                   ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xstrided_view.hpp:416:18: note: in instantiation of function template specialization 'std::copy<xt::xiterator<xt::xstepper<const xt::xarray_container<xt::uvector<double>, xt::layout_type::dynamic, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>, xt::xiterator<xt::xstepper<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>>' requested here
            std::copy(t.cbegin(), t.cend(), v.begin());
                 ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xstrided_view.hpp:424:31: note: in instantiation of function template specialization 'xt::xstrided_view_detail::run_assign_temporary_impl<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>, xt::xarray_container<xt::uvector<double>, xt::layout_type::dynamic, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>>>' requested here
        xstrided_view_detail::run_assign_temporary_impl(*this, tmp, std::integral_constant<bool, fast_assign>{});
                              ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xsemantic.hpp:662:30: note: in instantiation of member function 'xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>::assign_temporary_impl' requested here
        this->derived_cast().assign_temporary_impl(std::move(tmp));
                             ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xstrided_view.hpp:379:22: note: in instantiation of member function 'xt::xview_semantic<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>::assign_temporary' requested here
        return this->assign_temporary(std::move(tmp));
                     ^
/Users/dmitry/projects/gamma/client/libraries/xtensor/include/xtensor/xaxis_slice_iterator.hpp:28:11: note: in instantiation of member function 'xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>::operator=' requested here
    class xaxis_slice_iterator
          ^
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__algorithm/lower_bound.h:55:19: note: in instantiation of function template specialization 'std::__lower_bound<(lambda at /Users/dmitry/projects/gamma/client/logview/CurveObject.cpp:1209:31) &, xt::xaxis_slice_iterator<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>, double>' requested here
    return _VSTD::__lower_bound<_Comp_ref>(__first, __last, __value_, __comp);
                  ^
/Users/dmitry/projects/gamma/client/logview/CurveObject.cpp:1207:19: note: in instantiation of function template specialization 'std::lower_bound<xt::xaxis_slice_iterator<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>, double, (lambda at /Users/dmitry/projects/gamma/client/logview/CurveObject.cpp:1209:31)>' requested here
  auto iit = std::lower_bound(beginIt, endIt,
                  ^
/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/c++/v1/__algorithm/copy.h:32:1: note: candidate template ignored: substitution failure [with _InputIterator = xt::xiterator<xt::xstepper<const xt::xarray_container<xt::uvector<double>, xt::layout_type::dynamic, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>, _OutputIterator = xt::xiterator<xt::xstepper<xt::xstrided_view<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::layout_type::dynamic, xt::detail::inner_storage_getter<const xt::xarray_container<xt::uvector<double>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &>>>, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true> *, xt::layout_type::row_major>]
__copy_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
^
3 errors generated.

I believe, const ref arrays should be "iterable" the same way as non-const variables.

Thanks

paceholder avatar Mar 13 '23 10:03 paceholder