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