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