Reference documentation for deal.II version GIT 20f059c89a 2022-12-04 14:55:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
array_view.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2021 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_array_view_h
17 #define dealii_array_view_h
18 
19 #include <deal.II/base/config.h>
20 
24 #include <deal.II/base/tensor.h>
25 
26 #include <type_traits>
27 #include <vector>
28 
30 
31 // Forward declaration
32 template <int N, typename T>
33 class Table;
34 
35 template <typename number>
36 class LAPACKFullMatrix;
37 
38 
80 template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
81 class ArrayView
82 {
83 public:
89 
93  using iterator = value_type *;
94 
98  using const_iterator = const ElementType *;
99 
104 
125 
135  ArrayView(const ArrayView<typename std::remove_cv<value_type>::type,
136  MemorySpaceType> &view);
137 
142  explicit ArrayView(value_type &element);
143 
159  const std::vector<typename std::remove_cv<value_type>::type> &vector);
160 
175  ArrayView(std::vector<typename std::remove_cv<value_type>::type> &vector);
176 
191  template <std::size_t N>
192  ArrayView(value_type (&array)[N]);
193 
202  template <std::size_t N>
204  const std::array<typename std::remove_cv<value_type>::type, N> &vector);
205 
214  template <std::size_t N>
215  ArrayView(std::array<typename std::remove_cv<value_type>::type, N> &vector);
216 
236  void
238 
244  bool
246  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
247 
253  bool
254  operator==(const ArrayView<typename std::remove_cv<value_type>::type,
255  MemorySpaceType> &other_view) const;
256 
262  bool
264  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
265 
271  bool
272  operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
273  MemorySpaceType> &other_view) const;
274 
279  std::size_t
280  size() const;
281 
286  value_type *
287  data() const noexcept;
288 
292  iterator
293  begin() const;
294 
298  iterator
299  end() const;
300 
305  cbegin() const;
306 
311  cend() const;
312 
325  value_type &
326  operator[](const std::size_t i) const;
327 
328 private:
334 
338  std::size_t n_elements;
339 
340  friend class ArrayView<const ElementType, MemorySpaceType>;
341 };
342 
343 
344 
345 //---------------------------------------------------------------------------
346 
347 
348 namespace internal
349 {
350  namespace ArrayViewHelper
351  {
352  template <typename MemorySpaceType>
353  inline bool
354  is_in_correct_memory_space(const void *const ptr)
355  {
356 #ifndef DEAL_II_COMPILER_CUDA_AWARE
357  (void)ptr;
358  static_assert(std::is_same<MemorySpaceType, MemorySpace::Host>::value,
359  "If the compiler doesn't understand CUDA code, "
360  "the only possible memory space is 'MemorySpace::Host'!");
361  return true;
362 #else
363  cudaPointerAttributes attributes;
364  const cudaError_t cuda_error = cudaPointerGetAttributes(&attributes, ptr);
365  if (cuda_error != cudaErrorInvalidValue)
366  {
367  AssertCuda(cuda_error);
368  if (std::is_same<MemorySpaceType, MemorySpace::Host>::value)
369  return (attributes.type == cudaMemoryTypeHost) ||
370  (attributes.type == cudaMemoryTypeUnregistered);
371  else
372  return attributes.type == cudaMemoryTypeDevice;
373  }
374  else
375  {
376  // ignore and reset the error since host pointers produce an error
377  cudaGetLastError();
378  return std::is_same<MemorySpaceType, MemorySpace::Host>::value;
379  }
380 #endif
381  }
382  } // namespace ArrayViewHelper
383 } // namespace internal
384 
385 
386 
387 template <typename ElementType, typename MemorySpaceType>
389  : starting_element(nullptr)
390  , n_elements(0)
391 {}
392 
393 
394 
395 template <typename ElementType, typename MemorySpaceType>
397  value_type * starting_element,
398  const std::size_t n_elements)
399  : starting_element(starting_element)
400  , n_elements(n_elements)
401 {
402  Assert(
403  n_elements == 0 ||
404  internal::ArrayViewHelper::is_in_correct_memory_space<MemorySpaceType>(
406  ExcMessage("The memory space indicated by the template parameter "
407  "and the one derived from the pointer value do not match!"));
408 }
409 
410 
411 
412 template <typename ElementType, typename MemorySpaceType>
413 inline void
415  const std::size_t n_elements)
416 {
417  this->starting_element = starting_element;
418  this->n_elements = n_elements;
419 }
420 
421 
422 
423 template <typename ElementType, typename MemorySpaceType>
425  : starting_element(&element)
426  , n_elements(1)
427 {}
428 
429 
430 
431 template <typename ElementType, typename MemorySpaceType>
433  const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
434  &view)
435  : starting_element(view.starting_element)
436  , n_elements(view.n_elements)
437 {}
438 
439 
440 
441 template <typename ElementType, typename MemorySpaceType>
443  const std::vector<typename std::remove_cv<value_type>::type> &vector)
444  : // use delegating constructor
445  ArrayView(vector.data(), vector.size())
446 {
447  // the following static_assert is not strictly necessary because,
448  // if we got a const std::vector reference argument but ElementType
449  // is not itself const, then the call to the forwarding constructor
450  // above will already have failed: vector.data() will have returned
451  // a const pointer, but we need a non-const pointer.
452  //
453  // nevertheless, leave the static_assert in since it provides a
454  // more descriptive error message that will simply come after the first
455  // error produced above
456  static_assert(std::is_const<value_type>::value == true,
457  "This constructor may only be called if the ArrayView "
458  "object has a const value_type. In other words, you can "
459  "only create an ArrayView to const values from a const "
460  "std::vector.");
461 }
462 
463 
464 
465 template <typename ElementType, typename MemorySpaceType>
467  std::vector<typename std::remove_cv<value_type>::type> &vector)
468  : // use delegating constructor
469  ArrayView(vector.data(), vector.size())
470 {}
471 
472 
473 
474 template <typename ElementType, typename MemorySpaceType>
475 template <std::size_t N>
477  const std::array<typename std::remove_cv<value_type>::type, N> &vector)
478  : // use delegating constructor
479  ArrayView(vector.data(), vector.size())
480 {
481  // the following static_assert is not strictly necessary because,
482  // if we got a const std::array reference argument but ElementType
483  // is not itself const, then the call to the forwarding constructor
484  // above will already have failed: vector.data() will have returned
485  // a const pointer, but we need a non-const pointer.
486  //
487  // nevertheless, leave the static_assert in since it provides a
488  // more descriptive error message that will simply come after the first
489  // error produced above
490  static_assert(std::is_const<value_type>::value == true,
491  "This constructor may only be called if the ArrayView "
492  "object has a const value_type. In other words, you can "
493  "only create an ArrayView to const values from a const "
494  "std::array.");
495 }
496 
497 
498 
499 template <typename ElementType, typename MemorySpaceType>
500 template <std::size_t N>
502  ElementType (&array)[N])
503  : ArrayView(&array[0], N)
504 {}
505 
506 
507 
508 template <typename ElementType, typename MemorySpaceType>
509 template <std::size_t N>
511  std::array<typename std::remove_cv<value_type>::type, N> &vector)
512  : // use delegating constructor
513  ArrayView(vector.data(), vector.size())
514 {}
515 
516 
517 
518 template <typename ElementType, typename MemorySpaceType>
519 inline bool
521  const ArrayView<const value_type, MemorySpaceType> &other_view) const
522 {
523  return (other_view.data() == starting_element) &&
524  (other_view.size() == n_elements);
525 }
526 
527 
528 
529 template <typename ElementType, typename MemorySpaceType>
530 inline bool
532  const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
533  &other_view) const
534 {
535  return (other_view.data() == starting_element) &&
536  (other_view.size() == n_elements);
537 }
538 
539 
540 
541 template <typename ElementType, typename MemorySpaceType>
542 inline bool
544  const ArrayView<const value_type, MemorySpaceType> &other_view) const
545 {
546  return !(*this == other_view);
547 }
548 
549 
550 
551 template <typename ElementType, typename MemorySpaceType>
554 {
555  if (n_elements == 0)
556  return nullptr;
557  else
558  return starting_element;
559 }
560 
561 
562 
563 template <typename ElementType, typename MemorySpaceType>
564 inline bool
566  const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
567  &other_view) const
568 {
569  return !(*this == other_view);
570 }
571 
572 
573 
574 template <typename ElementType, typename MemorySpaceType>
575 inline std::size_t
577 {
578  return n_elements;
579 }
580 
581 
582 
583 template <typename ElementType, typename MemorySpaceType>
586 {
587  return starting_element;
588 }
589 
590 
591 
592 template <typename ElementType, typename MemorySpaceType>
595 {
596  return starting_element + n_elements;
597 }
598 
599 
600 
601 template <typename ElementType, typename MemorySpaceType>
604 {
605  return starting_element;
606 }
607 
608 
609 
610 template <typename ElementType, typename MemorySpaceType>
613 {
614  return starting_element + n_elements;
615 }
616 
617 
618 
619 template <typename ElementType, typename MemorySpaceType>
622 {
623  AssertIndexRange(i, n_elements);
624  Assert(
625  (std::is_same<MemorySpaceType, MemorySpace::Host>::value),
626  ExcMessage(
627  "Accessing elements is only allowed if the data is stored in CPU memory!"));
628 
629  return *(starting_element + i);
630 }
631 
632 
633 
634 #ifndef DOXYGEN
635 namespace internal
636 {
637  namespace ArrayViewHelper
638  {
644  template <class Iterator>
645  bool
646  is_contiguous(const Iterator &first, const Iterator &last)
647  {
648  const auto n = std::distance(first, last);
649  for (typename std::decay<decltype(n)>::type i = 0; i < n; ++i)
650  if (std::addressof(*(std::next(first, i))) !=
651  std::next(std::addressof(*first), i))
652  return false;
653  return true;
654  }
655 
656 
667  template <class T>
668  constexpr bool
669  is_contiguous(T *, T *)
670  {
671  return true;
672  }
673  } // namespace ArrayViewHelper
674 } // namespace internal
675 #endif
676 
677 
678 
695 template <typename Iterator, typename MemorySpaceType = MemorySpace::Host>
696 ArrayView<typename std::remove_reference<
697  typename std::iterator_traits<Iterator>::reference>::type,
698  MemorySpaceType>
699 make_array_view(const Iterator begin, const Iterator end)
700 {
701  static_assert(
702  std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
703  typename std::random_access_iterator_tag>::value,
704  "The provided iterator should be a random access iterator.");
705  Assert(begin <= end,
706  ExcMessage(
707  "The beginning of the array view should be before the end."));
708  Assert(internal::ArrayViewHelper::is_contiguous(begin, end),
709  ExcMessage("The provided range isn't contiguous in memory!"));
710  // the reference type, not the value type, knows the constness of the iterator
711  return ArrayView<typename std::remove_reference<
712  typename std::iterator_traits<Iterator>::reference>::type,
713  MemorySpaceType>(std::addressof(*begin), end - begin);
714 }
715 
716 
717 
727 template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
730 {
731  Assert(begin <= end,
732  ExcMessage(
733  "The beginning of the array view should be before the end."));
735 }
736 
737 
738 
749 template <typename Number, typename MemorySpaceType>
752 {
753  return make_array_view(array_view.cbegin(), array_view.cend());
754 }
755 
756 
757 
768 template <typename Number, typename MemorySpaceType>
771 {
772  return make_array_view(array_view.begin(), array_view.end());
773 }
774 
775 
776 
798 template <int rank, int dim, typename Number>
801 {
802  return make_array_view(tensor.begin_raw(), tensor.end_raw());
803 }
804 
805 
806 
828 template <int rank, int dim, typename Number>
831 {
832  return make_array_view(tensor.begin_raw(), tensor.end_raw());
833 }
834 
835 
836 
858 template <int rank, int dim, typename Number>
861 {
862  return make_array_view(tensor.begin_raw(), tensor.end_raw());
863 }
864 
865 
866 
889 template <int rank, int dim, typename Number>
892 {
893  return make_array_view(tensor.begin_raw(), tensor.end_raw());
894 }
895 
896 
897 
911 template <typename ElementType, int N>
913 {
914  return ArrayView<ElementType>(array, N);
915 }
916 
917 
918 
933 template <typename ElementType>
936 {
937  return ArrayView<ElementType>(vector.begin(), vector.size());
938 }
939 
940 
941 
956 template <typename ElementType>
959 {
960  return ArrayView<const ElementType>(vector.begin(), vector.size());
961 }
962 
963 
964 
979 template <typename ElementType>
981 make_array_view(std::vector<ElementType> &vector)
982 {
983  return ArrayView<ElementType>(vector.data(), vector.size());
984 }
985 
986 
987 
1002 template <typename ElementType>
1004 make_array_view(const std::vector<ElementType> &vector)
1005 {
1006  return ArrayView<const ElementType>(vector.data(), vector.size());
1007 }
1008 
1009 
1010 
1030 template <typename ElementType>
1032 make_array_view(std::vector<ElementType> &vector,
1033  const std::size_t starting_index,
1034  const std::size_t size_of_view)
1035 {
1036  Assert(starting_index + size_of_view <= vector.size(),
1037  ExcMessage("The starting index and size of the view you want to "
1038  "create would lead to a view that extends beyond the end "
1039  "of the given vector."));
1040  return ArrayView<ElementType>(&vector[starting_index], size_of_view);
1041 }
1042 
1043 
1044 
1064 template <typename ElementType>
1066 make_array_view(const std::vector<ElementType> &vector,
1067  const std::size_t starting_index,
1068  const std::size_t size_of_view)
1069 {
1070  Assert(starting_index + size_of_view <= vector.size(),
1071  ExcMessage("The starting index and size of the view you want to "
1072  "create would lead to a view that extends beyond the end "
1073  "of the given vector."));
1074  return ArrayView<const ElementType>(&vector[starting_index], size_of_view);
1075 }
1076 
1077 
1078 
1095 template <typename ElementType>
1098  const typename Table<2, ElementType>::size_type row)
1099 {
1100  AssertIndexRange(row, table.size()[0]);
1101  return ArrayView<ElementType>(&table[row][0], table.size()[1]);
1102 }
1103 
1104 
1105 
1122 template <typename ElementType>
1125 {
1126  return ArrayView<ElementType>(&table[0][0], table.n_elements());
1127 }
1128 
1129 
1130 
1147 template <typename ElementType>
1150 {
1151  return ArrayView<const ElementType>(&table[0][0], table.n_elements());
1152 }
1153 
1154 
1172 template <typename ElementType>
1175 {
1176  return ArrayView<ElementType>(&matrix(0, 0), matrix.n_elements());
1177 }
1178 
1179 
1180 
1197 template <typename ElementType>
1200 {
1201  return ArrayView<const ElementType>(&matrix(0, 0), matrix.n_elements());
1202 }
1203 
1204 
1205 
1222 template <typename ElementType>
1225  const typename Table<2, ElementType>::size_type row)
1226 {
1227  AssertIndexRange(row, table.size()[0]);
1228  return ArrayView<const ElementType>(&table[row][0], table.size()[1]);
1229 }
1230 
1231 
1232 
1252 template <typename ElementType>
1255  const typename Table<2, ElementType>::size_type row,
1256  const typename Table<2, ElementType>::size_type starting_column,
1257  const std::size_t size_of_view)
1258 {
1259  AssertIndexRange(row, table.size()[0]);
1260  AssertIndexRange(starting_column, table.size()[1]);
1261  Assert(starting_column + size_of_view <= table.size()[1],
1262  ExcMessage("The starting index and size of the view you want to "
1263  "create would lead to a view that extends beyond the end "
1264  "of a column of the given table."));
1265  return ArrayView<ElementType>(&table[row][starting_column], size_of_view);
1266 }
1267 
1268 
1269 
1289 template <typename ElementType>
1292  const typename Table<2, ElementType>::size_type row,
1293  const typename Table<2, ElementType>::size_type starting_column,
1294  const std::size_t size_of_view)
1295 {
1296  AssertIndexRange(row, table.size()[0]);
1297  AssertIndexRange(starting_column, table.size()[1]);
1298  Assert(starting_column + size_of_view <= table.size()[1],
1299  ExcMessage("The starting index and size of the view you want to "
1300  "create would lead to a view that extends beyond the end "
1301  "of a column of the given table."));
1302  return ArrayView<const ElementType>(&table[row][starting_column],
1303  size_of_view);
1304 }
1305 
1306 
1307 
1308 /*
1309  * Create a view that doesn't allow the container it points to to be modified.
1310  * This is useful if the object passed in is not `const` already and a function
1311  * requires a view to constant memory in its signature.
1312  *
1313  * This function returns an object of type `ArrayView<const T>` where `T` is the
1314  * element type of the container.
1315  *
1316  * @relatesalso ArrayView
1317  */
1318 template <typename Container>
1319 inline auto
1320 make_const_array_view(const Container &container)
1321  -> decltype(make_array_view(container))
1322 {
1323  return make_array_view(container);
1324 }
1325 
1326 
1328 
1329 #endif
auto make_const_array_view(const Container &container) -> decltype(make_array_view(container))
Definition: array_view.h:1320
ArrayView< const ElementType > make_array_view(const Vector< ElementType > &vector)
Definition: array_view.h:958
ArrayView(value_type &element)
Definition: array_view.h:424
iterator begin() const
Definition: array_view.h:585
ArrayView(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &view)
Definition: array_view.h:432
ArrayView< Number, MemorySpaceType > make_array_view(ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:770
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition: array_view.h:699
value_type * iterator
Definition: array_view.h:93
ArrayView< Number > make_array_view(SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:891
value_type & operator[](const std::size_t i) const
Definition: array_view.h:621
ArrayView< const ElementType > make_array_view(const LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1199
ArrayView< const Number > make_array_view(const Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:800
ArrayView< const Number > make_array_view(const SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:860
ArrayView< ElementType > make_array_view(LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1174
ArrayView< ElementType > make_array_view(ElementType(&array)[N])
Definition: array_view.h:912
ArrayView< ElementType, MemorySpaceType > make_array_view(ElementType *const begin, ElementType *const end)
Definition: array_view.h:729
bool operator!=(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &other_view) const
Definition: array_view.h:565
const_iterator cend() const
Definition: array_view.h:612
iterator end() const
Definition: array_view.h:594
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector, const std::size_t starting_index, const std::size_t size_of_view)
Definition: array_view.h:1066
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table)
Definition: array_view.h:1149
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row, const typename Table< 2, ElementType >::size_type starting_column, const std::size_t size_of_view)
Definition: array_view.h:1291
ArrayView(const std::array< typename std::remove_cv< value_type >::type, N > &vector)
Definition: array_view.h:476
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector)
Definition: array_view.h:981
ArrayView(std::vector< typename std::remove_cv< value_type >::type > &vector)
Definition: array_view.h:466
bool operator==(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:520
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector, const std::size_t starting_index, const std::size_t size_of_view)
Definition: array_view.h:1032
bool operator!=(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:543
const_iterator cbegin() const
Definition: array_view.h:603
ArrayView(const std::vector< typename std::remove_cv< value_type >::type > &vector)
Definition: array_view.h:442
ArrayView(value_type(&array)[N])
Definition: array_view.h:501
ArrayView< Number > make_array_view(Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:830
value_type * data() const noexcept
Definition: array_view.h:553
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row, const typename Table< 2, ElementType >::size_type starting_column, const std::size_t size_of_view)
Definition: array_view.h:1254
void reinit(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:414
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table)
Definition: array_view.h:1124
value_type * starting_element
Definition: array_view.h:333
std::size_t size() const
Definition: array_view.h:576
bool operator==(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &other_view) const
Definition: array_view.h:531
ElementType value_type
Definition: array_view.h:88
ArrayView(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:396
std::size_t n_elements
Definition: array_view.h:338
ArrayView< const Number, MemorySpaceType > make_array_view(const ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:751
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1224
const ElementType * const_iterator
Definition: array_view.h:98
ArrayView< ElementType > make_array_view(Vector< ElementType > &vector)
Definition: array_view.h:935
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1097
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector)
Definition: array_view.h:1004
ArrayView(std::array< typename std::remove_cv< value_type >::type, N > &vector)
Definition: array_view.h:510
Number * begin_raw()
Number * end_raw()
Definition: tensor.h:503
Number * end_raw()
Number * begin_raw()
Definition: vector.h:109
size_type size() const
iterator begin()
#define DEAL_II_DEPRECATED
Definition: config.h:164
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:458
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:459
Point< 2 > first
Definition: grid_out.cc:4605
#define Assert(cond, exc)
Definition: exceptions.h:1501
#define AssertIndexRange(index, range)
Definition: exceptions.h:1760
#define AssertCuda(error_code)
Definition: exceptions.h:1844
static ::ExceptionBase & ExcMessage(std::string arg1)
@ matrix
Contents is actually a matrix.
static const char T
static const char N
VectorType::value_type * begin(VectorType &V)
VectorType::value_type * end(VectorType &V)
bool is_in_correct_memory_space(const void *const ptr)
Definition: array_view.h:354