Logo ROOT   6.08/07
Reference Guide
rhysd_array_view.hxx
Go to the documentation of this file.
1 /// \file ROOT/rhysd_array_view.h
2 /// \ingroup Base StdExt ROOT7
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2015-09-06
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
6 
7 /*************************************************************************
8  * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
9  * All rights reserved. *
10  * *
11  * For the licensing terms see $ROOTSYS/LICENSE. *
12  * For the list of contributors see $ROOTSYS/README/CREDITS. *
13  *************************************************************************/
14 
15 #ifndef ROOT7_RHYSD_ARRAY_VIEW_H
16 #define ROOT7_RHYSD_ARRAY_VIEW_H
17 
18 // From https://github.com/rhysd/array_view/blob/master/include/array_view.hpp
19 
20 #include <cstddef>
21 #include <iterator>
22 #include <array>
23 #include <vector>
24 #include <stdexcept>
25 #include <memory>
26 #include <type_traits>
27 #include <vector>
28 #include <initializer_list>
29 
30 namespace std {
31 
32 inline namespace __ROOT {
33 
34 using std::size_t;
35 
36 namespace detail {
37 // detail meta functions {{{
38 template<class Array>
40  static bool const value = false;
41 };
42 template<class T, size_t N>
43 struct is_array_class<std::array<T, N>> {
44  static bool const value = true;
45 };
46 template<class T>
47 struct is_array_class<std::vector<T>> {
48  static bool const value = true;
49 };
50 template<class T>
51 struct is_array_class<std::initializer_list<T>> {
52  static bool const value = true;
53 };
54 // }}}
55 
56 // index sequences {{{
57 template< size_t... Indices >
58 struct indices{
59  static constexpr size_t value[sizeof...(Indices)] = {Indices...};
60 };
61 
62 template<class IndicesType, size_t Next>
64 
65 template<size_t... Indices, size_t Next>
66 struct make_indices_next<indices<Indices...>, Next> {
67  typedef indices<Indices..., (Indices + Next)...> type;
68 };
69 
70 template<class IndicesType, size_t Next, size_t Tail>
72 
73 template<size_t... Indices, size_t Next, size_t Tail>
74 struct make_indices_next2<indices<Indices...>, Next, Tail> {
75  typedef indices<Indices..., (Indices + Next)..., Tail> type;
76 };
77 
78 template<size_t First, size_t Step, size_t N, class = void>
80 
81 template<size_t First, size_t Step, size_t N>
83  First,
84  Step,
85  N,
86  typename std::enable_if<(N == 0)>::type
87 > {
88  typedef indices<> type;
89 };
90 
91 template<size_t First, size_t Step, size_t N>
93  First,
94  Step,
95  N,
96  typename std::enable_if<(N == 1)>::type
97 > {
99 };
100 
101 template<size_t First, size_t Step, size_t N>
103  First,
104  Step,
105  N,
106  typename std::enable_if<(N > 1 && N % 2 == 0)>::type
107 >
109  typename detail::make_indices_impl<First, Step, N / 2>::type,
110  First + N / 2 * Step
111  >
112 {};
113 
114 template<size_t First, size_t Step, size_t N>
115 struct make_indices_impl<
116  First,
117  Step,
118  N,
119  typename std::enable_if<(N > 1 && N % 2 == 1)>::type
120 >
122  typename detail::make_indices_impl<First, Step, N / 2>::type,
123  First + N / 2 * Step,
124  First + (N - 1) * Step
125  >
126 {};
127 
128 template<size_t First, size_t Last, size_t Step = 1>
131  First,
132  Step,
133  ((Last - First) + (Step - 1)) / Step
134  >
135 {};
136 
137 template < size_t Start, size_t Last, size_t Step = 1 >
139 // }}}
140 } // namespace detail
141 
142 // array_view {{{
143 
144 struct check_bound_t {};
145 static constexpr check_bound_t check_bound{};
146 
147 template<class T>
148 class array_view {
149 public:
150  /*
151  * types
152  */
153  typedef T value_type;
154  typedef value_type const* pointer;
155  typedef value_type const* const_pointer;
156  typedef value_type const& reference;
157  typedef value_type const& const_reference;
158  typedef value_type const* iterator;
159  typedef value_type const* const_iterator;
160  typedef size_t size_type;
161  typedef ptrdiff_t difference_type;
162  typedef std::reverse_iterator<iterator> reverse_iterator;
163  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
164 
165  /*
166  * ctors and assign operators
167  */
168  constexpr array_view() noexcept
169  : length_(0), data_(nullptr)
170  {}
171 
172  constexpr array_view(array_view const&) noexcept = default;
173  constexpr array_view(array_view &&) noexcept = default;
174 
175  // Note:
176  // This constructor can't be constexpr because & operator can't be constexpr.
177  template<size_type N>
178  /*implicit*/ array_view(std::array<T, N> const& a) noexcept
179  : length_(N), data_(N > 0 ? a.data() : nullptr)
180  {}
181 
182  // Note:
183  // This constructor can't be constexpr because & operator can't be constexpr.
184  template<size_type N>
185  /*implicit*/ array_view(T const (& a)[N]) noexcept
186  : length_(N), data_(N > 0 ? std::addressof(a[0]) : nullptr)
187  {
188  static_assert(N > 0, "Zero-length array is not permitted in ISO C++.");
189  }
190 
191  /*implicit*/ array_view(std::vector<T> const& v) noexcept
192  : length_(v.size()), data_(v.empty() ? nullptr : v.data())
193  {}
194 
195  /*implicit*/ constexpr array_view(T const* a, size_type const n) noexcept
196  : length_(n), data_(a)
197  {}
198 
199  template<
200  class InputIterator,
201  class = typename std::enable_if<
202  std::is_same<
203  T,
204  typename std::iterator_traits<InputIterator>::value_type
205  >::value
206  >::type
207  >
208  explicit array_view(InputIterator start, InputIterator last)
209  : length_(std::distance(start, last)), data_(start)
210  {}
211 
212  array_view(std::initializer_list<T> const& l)
213  : length_(l.size()), data_(std::begin(l))
214  {}
215 
216  array_view& operator=(array_view const&) noexcept = delete;
217  array_view& operator=(array_view &&) noexcept = delete;
218 
219  /*
220  * iterator interfaces
221  */
222  constexpr const_iterator begin() const noexcept
223  {
224  return data_;
225  }
226  constexpr const_iterator end() const noexcept
227  {
228  return data_ + length_;
229  }
230  constexpr const_iterator cbegin() const noexcept
231  {
232  return begin();
233  }
234  constexpr const_iterator cend() const noexcept
235  {
236  return end();
237  }
238  const_reverse_iterator rbegin() const
239  {
240  return {end()};
241  }
242  const_reverse_iterator rend() const
243  {
244  return {begin()};
245  }
246  const_reverse_iterator crbegin() const
247  {
248  return rbegin();
249  }
250  const_reverse_iterator crend() const
251  {
252  return rend();
253  }
254 
255  /*
256  * access
257  */
258  constexpr size_type size() const noexcept
259  {
260  return length_;
261  }
262  constexpr size_type length() const noexcept
263  {
264  return size();
265  }
266  constexpr size_type max_size() const noexcept
267  {
268  return size();
269  }
270  constexpr bool empty() const noexcept
271  {
272  return length_ == 0;
273  }
274  constexpr const_reference operator[](size_type const n) const noexcept
275  {
276  return *(data_ + n);
277  }
278  constexpr const_reference at(size_type const n) const
279  {
280  if (n >= length_) throw std::out_of_range("array_view::at()");
281  return *(data_ + n);
282  }
283  constexpr const_pointer data() const noexcept
284  {
285  return data_;
286  }
287  constexpr const_reference front() const noexcept
288  {
289  return *data_;
290  }
291  constexpr const_reference back() const noexcept
292  {
293  return *(data_ + length_ - 1);
294  }
295 
296  /*
297  * slices
298  */
299  // slice with indices {{{
300  // check bound {{{
301  constexpr array_view<T> slice(check_bound_t, size_type const pos, size_type const slicelen) const
302  {
303  if (pos >= length_ || pos + slicelen >= length_) {
304  throw std::out_of_range("array_view::slice()");
305  }
306  return array_view<T>{begin() + pos, begin() + pos + slicelen};
307  }
308  constexpr array_view<T> slice_before(check_bound_t, size_type const pos) const
309  {
310  if (pos >= length_) {
311  throw std::out_of_range("array_view::slice()");
312  }
313  return array_view<T>{begin(), begin() + pos};
314  }
315  constexpr array_view<T> slice_after(check_bound_t, size_type const pos) const
316  {
317  if (pos >= length_) {
318  throw std::out_of_range("array_view::slice()");
319  }
320  return array_view<T>{begin() + pos, end()};
321  }
322  // }}}
323  // not check bound {{{
324  constexpr array_view<T> slice(size_type const pos, size_type const slicelen) const
325  {
326  return array_view<T>{begin() + pos, begin() + pos + slicelen};
327  }
328  constexpr array_view<T> slice_before(size_type const pos) const
329  {
330  return array_view<T>{begin(), begin() + pos};
331  }
332  constexpr array_view<T> slice_after(size_type const pos) const
333  {
334  return array_view<T>{begin() + pos, end()};
335  }
336  // }}}
337  // }}}
338  // slice with iterators {{{
339  // check bound {{{
340  constexpr array_view<T> slice(check_bound_t, iterator start, iterator last) const
341  {
342  if ( start >= end() ||
343  last > end() ||
344  start > last ||
345  static_cast<size_t>(std::distance(start, last > end() ? end() : last)) > length_ - std::distance(begin(), start) ) {
346  throw std::out_of_range("array_view::slice()");
347  }
348  return array_view<T>{start, last > end() ? end() : last};
349  }
350  constexpr array_view<T> slice_before(check_bound_t, iterator const pos) const
351  {
352  if (pos < begin() || pos > end()) {
353  throw std::out_of_range("array_view::slice()");
354  }
355  return array_view<T>{begin(), pos > end() ? end() : pos};
356  }
357  constexpr array_view<T> slice_after(check_bound_t, iterator const pos) const
358  {
359  if (pos < begin() || pos > end()) {
360  throw std::out_of_range("array_view::slice()");
361  }
362  return array_view<T>{pos < begin() ? begin() : pos, end()};
363  }
364  // }}}
365  // not check bound {{{
366  constexpr array_view<T> slice(iterator start, iterator last) const
367  {
368  return array_view<T>{start, last};
369  }
370  constexpr array_view<T> slice_before(iterator const pos) const
371  {
372  return array_view<T>{begin(), pos};
373  }
374  constexpr array_view<T> slice_after(iterator const pos) const
375  {
376  return array_view<T>{pos, end()};
377  }
378  // }}}
379  // }}}
380 
381  /*
382  * others
383  */
384  template<class Allocator = std::allocator<T>>
385  auto to_vector(Allocator const& alloc = Allocator{}) const
386  -> std::vector<T, Allocator>
387  {
388  return {begin(), end(), alloc};
389  }
390 
391  template<size_t N>
392  auto to_array() const
393  -> std::array<T, N>
394  {
395  return to_array_impl(detail::make_indices<0, N>{});
396  }
397 private:
398  template<size_t... I>
400  -> std::array<T, sizeof...(I)>
401  {
402  return {{(I < length_ ? *(data_ + I) : T{} )...}};
403  }
404 
405 private:
406  size_type const length_;
407  const_pointer const data_;
408 };
409 // }}}
410 
411 // compare operators {{{
412 namespace detail {
413 template< class ArrayL, class ArrayR >
414 inline constexpr
415 bool operator_equal_impl(ArrayL const& lhs, size_t const lhs_size, ArrayR const& rhs, size_t const rhs_size)
416 {
417  if (lhs_size != rhs_size) {
418  return false;
419  }
420 
421  auto litr = std::begin(lhs);
422  auto ritr = std::begin(rhs);
423  for (; litr != std::end(lhs); ++litr, ++ritr) {
424  if (!(*litr == *ritr)) {
425  return false;
426  }
427  }
428 
429  return true;
430 }
431 } // namespace detail
432 
433 template<class T1, class T2>
434 inline constexpr
435 bool operator==(array_view<T1> const& lhs, array_view<T2> const& rhs)
436 {
437  return detail::operator_equal_impl(lhs, lhs.length(), rhs, rhs.length());
438 }
439 
440 template<
441  class T,
442  class Array,
443  class = typename std::enable_if<
445  >::type
446 >
447 inline constexpr
448 bool operator==(array_view<T> const& lhs, Array const& rhs)
449 {
450  return detail::operator_equal_impl(lhs, lhs.length(), rhs, rhs.size());
451 }
452 
453 template<class T1, class T2, size_t N>
454 inline constexpr
455 bool operator==(array_view<T1> const& lhs, T2 const (& rhs)[N])
456 {
457  return detail::operator_equal_impl(lhs, lhs.length(), rhs, N);
458 }
459 
460 template<
461  class T,
462  class Array,
463  class = typename std::enable_if<
464  is_array<Array>::value
465  >::type
466 >
467 inline constexpr
468 bool operator!=(array_view<T> const& lhs, Array const& rhs)
469 {
470  return !(lhs == rhs);
471 }
472 
473 template<
474  class Array,
475  class T,
476  class = typename std::enable_if<
477  is_array<Array>::value
478  >::type
479 >
480 inline constexpr
481 bool operator==(Array const& lhs, array_view<T> const& rhs)
482 {
483  return rhs == lhs;
484 }
485 
486 template<
487  class Array,
488  class T,
489  class = typename std::enable_if<
490  is_array<Array>::value,
491  Array
492  >::type
493 >
494 inline constexpr
495 bool operator!=(Array const& lhs, array_view<T> const& rhs)
496 {
497  return !(rhs == lhs);
498 }
499 // }}}
500 
501 // helpers to construct view {{{
502 template<
503  class Array,
504  class = typename std::enable_if<
506  >::type
507 >
508 inline constexpr
509 auto make_view(Array const& a)
511 {
512  return {a};
513 }
514 
515 template< class T, size_t N>
516 inline constexpr
518 {
519  return {a};
520 }
521 
522 template<class T>
523 inline constexpr
525 {
526  return array_view<T>{p, n};
527 }
528 
529 template<class InputIterator, class Result = array_view<typename std::iterator_traits<InputIterator>::value_type>>
530 inline constexpr
531 Result make_view(InputIterator begin, InputIterator end)
532 {
533  return Result{begin, end};
534 }
535 
536 template<class T>
537 inline constexpr
538 array_view<T> make_view(std::initializer_list<T> const& l)
539 {
540  return {l};
541 }
542 // }}}
543 
544 } // inline namespace __ROOT
545 } // namespace std
546 
547 
548 
549 
550 
551 #if 0
552 // This stuff is too complex for our simple use case!
553 
554 #include <cstddef>
555 #include <array>
556 #include <type_traits>
557 
558 // See N3851
559 
560 namespace std {
561 
562 template<int Rank>
563 class index;
564 
565 template<int Rank>
566 class bounds {
567 public:
568  static constexpr int rank = Rank;
569  using reference = ptrdiff_t &;
570  using const_reference = const ptrdiff_t &;
571  using size_type = size_t;
572  using value_type = ptrdiff_t;
573 
574 private:
575  std::array<value_type, Rank> m_B;
576 
577 public:
578  constexpr bounds() noexcept;
579 
580  constexpr bounds(value_type b) noexcept: m_B{{b}} { };
581  //constexpr bounds(const initializer_list<value_type>&) noexcept;
582  //constexpr bounds(const bounds&) noexcept;
583  //bounds& operator=(const bounds&) noexcept;
584 
585  reference operator[](size_type i) noexcept { return m_B[i]; }
586 
587  constexpr const_reference operator[](
588  size_type i) const noexcept { return m_B[i]; };
589 
590 
591  bool operator==(const bounds &rhs) const noexcept;
592 
593  bool operator!=(const bounds &rhs) const noexcept;
594 
595  bounds operator+(const index<rank> &rhs) const noexcept;
596 
597  bounds operator-(const index<rank> &rhs) const noexcept;
598 
599  bounds &operator+=(const index<rank> &rhs) noexcept;
600 
601  bounds &operator-=(const index<rank> &rhs) noexcept;
602 
603  constexpr size_type size() const noexcept;
604 
605  bool contains(const index<rank> &idx) const noexcept;
606  //bounds_iterator<rank> begin() const noexcept;
607  //bounds_iterator<rank> end() const noexcept;
608 
609 };
610 
611 //bounds operator+(const index<rank>& lhs, const bounds& rhs) noexcept;
612 
613 template<int Rank>
614 class index {
615 public:
616  static constexpr int rank = Rank;
617  using reference = ptrdiff_t &;
618  using const_reference = const ptrdiff_t &;
619  using size_type = size_t;
620  using value_type = ptrdiff_t;
621 
622 // For index<rank>:
623  constexpr index() noexcept;
624 
625  constexpr index(value_type) noexcept;
626 
627  constexpr index(const initializer_list<value_type> &) noexcept;
628 
629  constexpr index(const index &) noexcept;
630 
631  index &operator=(const index &) noexcept;
632 
633  reference operator[](size_type component_idx) noexcept;
634 
635  constexpr const_reference operator[](size_type component_idx) const noexcept;
636 
637  bool operator==(const index &rhs) const noexcept;
638 
639  bool operator!=(const index &rhs) const noexcept;
640 
641  index operator+(const index &rhs) const noexcept;
642 
643  index operator-(const index &rhs) const noexcept;
644 
645  index &operator+=(const index &rhs) noexcept;
646 
647  index &operator-=(const index &rhs) noexcept;
648 
649  index &operator++() noexcept;
650 
651  index operator++(int) noexcept;
652 
653  index &operator--() noexcept;
654 
655  index operator--(int) noexcept;
656 
657  index operator+() const noexcept;
658 
659  index operator-() const noexcept;
660 };
661 
662 /// Mock-up of future atd::(experimental::)array_view.
663 /// Supports only what we need for THist, e.g. Rank := 1.
664 template<typename ValueType, int Rank = 1>
665 class array_view {
666 public:
667  static constexpr int rank = Rank;
668  using index_type = index<rank>;
669  using bounds_type = bounds<rank>;
670  using size_type = typename bounds_type::size_type;
671  using value_type = ValueType;
672  using pointer = typename std::add_pointer_t<value_type>;
673  using reference = typename std::add_lvalue_reference_t<value_type>;
674 
675  constexpr array_view() noexcept;
676 
677  constexpr explicit array_view(std::vector<ValueType> &cont) noexcept;
678 
679  template<typename ArrayType>
680  constexpr explicit array_view(ArrayType &data) noexcept;
681 
682  template<typename ViewValueType>
683  constexpr array_view(const array_view<ViewValueType, rank> &rhs) noexcept;
684 
685  template<typename Container>
686  constexpr array_view(bounds_type bounds, Container &cont) noexcept;
687 
688  constexpr array_view(bounds_type bounds, pointer data) noexcept;
689 
690  template<typename ViewValueType>
691  array_view &operator=(const array_view<ViewValueType, rank> &rhs) noexcept;
692 
693  constexpr bounds_type bounds() const noexcept;
694  constexpr size_type size() const noexcept;
695  constexpr index_type stride() const noexcept;
696 
697  constexpr pointer data() const noexcept;
698  constexpr reference operator[](const index_type& idx) const noexcept;
699 };
700 
701 }
702 #endif // too complex!
703 #endif
constexpr const_pointer data() const noexcept
array_view(InputIterator start, InputIterator last)
constexpr array_view< T > slice_before(iterator const pos) const
constexpr const_iterator cbegin() const noexcept
double T(double x)
Definition: ChebyshevPol.h:34
std::reverse_iterator< const_iterator > const_reverse_iterator
constexpr const_iterator end() const noexcept
constexpr array_view() noexcept
constexpr array_view< T > slice(check_bound_t, iterator start, iterator last) const
static constexpr check_bound_t check_bound
void Step(const gsl_rng *r, void *xp, double step_size)
constexpr size_type max_size() const noexcept
#define N
value_type const * pointer
constexpr const_iterator begin() const noexcept
TArc * a
Definition: textangle.C:12
const_reverse_iterator rend() const
STL namespace.
value_type const & reference
constexpr const_reference operator[](size_type const n) const noexcept
constexpr array_view< T > slice_before(size_type const pos) const
array_view(std::initializer_list< T > const &l)
constexpr const_iterator cend() const noexcept
constexpr bool operator_equal_impl(ArrayL const &lhs, size_t const lhs_size, ArrayR const &rhs, size_t const rhs_size)
constexpr array_view< T > slice_before(check_bound_t, iterator const pos) const
constexpr array_view(T const *a, size_type const n) noexcept
constexpr array_view< T > slice(size_type const pos, size_type const slicelen) const
TTime operator-(const TTime &t1, const TTime &t2)
Definition: TTime.h:85
std::reverse_iterator< iterator > reverse_iterator
constexpr auto make_view(Array const &a) -> array_view< typename Array::value_type >
TString operator+(const TString &s1, const TString &s2)
Use the special concatenation constructor.
Definition: TString.cxx:1438
auto to_vector(Allocator const &alloc=Allocator{}) const -> std::vector< T, Allocator >
const_reverse_iterator crend() const
array_view(std::vector< T > const &v) noexcept
value_type const * iterator
auto to_array_impl(detail::indices< I... >) const -> std::array< T, sizeof...(I)>
constexpr array_view< T > slice_after(check_bound_t, iterator const pos) const
constexpr const_reference back() const noexcept
const_pointer const data_
const char * Array
SVector< double, 2 > v
Definition: Dict.h:5
const_reverse_iterator rbegin() const
constexpr bool operator==(array_view< T1 > const &lhs, array_view< T2 > const &rhs)
TLine * l
Definition: textangle.C:4
constexpr array_view< T > slice_after(iterator const pos) const
constexpr array_view< T > slice_after(check_bound_t, size_type const pos) const
constexpr array_view< T > slice_after(size_type const pos) const
int type
Definition: TGX11.cxx:120
#define T2
Definition: md5.inl:146
constexpr array_view< T > slice_before(check_bound_t, size_type const pos) const
array_view(T const (&a)[N]) noexcept
typename make_indices_< Start, Last, Step >::type make_indices
constexpr array_view< T > slice(check_bound_t, size_type const pos, size_type const slicelen) const
value_type const * const_pointer
auto to_array() const -> std::array< T, N >
constexpr size_type length() const noexcept
constexpr const_reference at(size_type const n) const
constexpr bool empty() const noexcept
constexpr array_view< T > slice(iterator start, iterator last) const
#define nullptr
Definition: Rtypes.h:87
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
value_type const * const_iterator
constexpr size_type size() const noexcept
#define I(x, y, z)
constexpr bool operator!=(array_view< T > const &lhs, Array const &rhs)
value_type const & const_reference
const Int_t n
Definition: legend1.C:16
array_view(std::array< T, N > const &a) noexcept
constexpr const_reference front() const noexcept
const_reverse_iterator crbegin() const