Repository: xtensor-stack/xtensor (language: python)

Issue:
Copy of a view of const data doesn't compile
I have large arrays on disk which I read-only memory map and use through `xt::adapt`. This works fine, but anything that tries to take a copy of a view will fail to compile due to the constness of the data.

Minimal example, [godbolt](https://godbolt.org/z/s6o598):
```cpp
#include <xtensor/xadapt.hpp>
#include <xtensor/xview.hpp>

std::array<const float, 4> array{1, 2, 3, 4};
std::vector<size_t> shape = {2, 2};
std::vector<size_t> strides = {2, 1};

auto a = xt::adapt(array.data(), array.size(), xt::no_ownership(), shape, strides);
auto v = xt::row(a, 0);

// Compile error for anything which tries to make a copy of the view data
xt::xarray<float> a2 = v; // Fails to compile
std::vector<float>(v.cbegin(), v.cend()); // Fails to compile
```
Error:
```
[...]
xcontainer.hpp:567:30: error: invalid conversion from 'xt::detail::xbuffer_storage<const float*, std::allocator<float> >::pointer' {aka 'const float*'} to 'xt::xcontainer<xt::xarray_adaptor<xt::xbuffer_adaptor<const float*, xt::no_ownership, std::allocator<float> >, xt::layout_type::dynamic, std::vector<long unsigned int, std::allocator<long unsigned int> >, xt::xtensor_expression_tag> >::value_type*' {aka 'float*'} [-fpermissive]
  567 |         return storage().data();
      |                ~~~~~~~~~~~~~~^~
      |                              |
      |                              xt::detail::xbuffer_storage<const float*, std::allocator<float> >::pointer {aka const float*}
```

This works for STL-like containers (`auto a = xt::adapt(array, shape)`).


Discussion / hints:

Fix patch:
diff --git a/include/xtensor/xcontainer.hpp b/include/xtensor/xcontainer.hpp
index 730362e3b..06917bcaa 100644
--- a/include/xtensor/xcontainer.hpp
+++ b/include/xtensor/xcontainer.hpp
@@ -152,8 +152,8 @@ namespace xt
         storage_type& storage() noexcept;
         const storage_type& storage() const noexcept;
 
-        value_type* data() noexcept;
-        const value_type* data() const noexcept;
+        pointer data() noexcept;
+        const_pointer data() const noexcept;
         const size_type data_offset() const noexcept;
 
         template <class S>
@@ -562,7 +562,7 @@ namespace xt
      * container is empty (data() is not is not dereferenceable in that case)
      */
     template <class D>
-    inline auto xcontainer<D>::data() noexcept -> value_type*
+    inline auto xcontainer<D>::data() noexcept -> pointer
     {
         return storage().data();
     }
@@ -573,7 +573,7 @@ namespace xt
     * container is empty (data() is not is not dereferenceable in that case)
     */
     template <class D>
-    inline auto xcontainer<D>::data() const noexcept -> const value_type*
+    inline auto xcontainer<D>::data() const noexcept -> const_pointer
     {
         return storage().data();
     }


Test patch:
diff --git a/test/test_xadapt.cpp b/test/test_xadapt.cpp
index b966dd166..25a4121cf 100644
--- a/test/test_xadapt.cpp
+++ b/test/test_xadapt.cpp
@@ -221,6 +221,7 @@ namespace xt
         auto a0_view = adapt(const_data, size, no_ownership());
         a0(3) = 3;
         EXPECT_EQ(3, a0_view[3]);
+        EXPECT_EQ(a0.data(), a0_view.data());
 
         using shape_type = std::array<vec_type::size_type, 2>;
         shape_type s = {2, 2};
diff --git a/test/test_xview.cpp b/test/test_xview.cpp
index 150c29ae5..fba27e703 100644
--- a/test/test_xview.cpp
+++ b/test/test_xview.cpp
@@ -1586,8 +1586,6 @@ namespace xt
             { 3, 4 },
         };
 
-        std::cout << tensor.shape().size() << std::endl;
-
         const auto row0 = xt::row(tensor, 0);
         const auto row1 = xt::row(tensor, 1);