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