• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef BOOST_HISTOGRAM_DETAIL_SUB_ARRAY_HPP
8 #define BOOST_HISTOGRAM_DETAIL_SUB_ARRAY_HPP
9 
10 #include <algorithm>
11 #include <stdexcept>
12 
13 namespace boost {
14 namespace histogram {
15 namespace detail {
16 
17 template <class T, std::size_t N>
18 class sub_array {
swap_element_is_noexcept()19   constexpr bool swap_element_is_noexcept() noexcept {
20     using std::swap;
21     return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
22   }
23 
24 public:
25   using value_type = T;
26   using size_type = std::size_t;
27   using reference = T&;
28   using const_reference = const T&;
29   using pointer = T*;
30   using const_pointer = const T*;
31   using iterator = pointer;
32   using const_iterator = const_pointer;
33 
34   sub_array() = default;
35 
sub_array(std::size_t s)36   explicit sub_array(std::size_t s) noexcept : size_(s) { assert(size_ <= N); }
37 
sub_array(std::size_t s,const T & value)38   sub_array(std::size_t s, const T& value) noexcept(
39       std::is_nothrow_assignable<T, const_reference>::value)
40       : sub_array(s) {
41     fill(value);
42   }
43 
at(size_type pos)44   reference at(size_type pos) noexcept {
45     if (pos >= size()) throw std::out_of_range{"pos is out of range"};
46     return data_[pos];
47   }
48 
at(size_type pos) const49   const_reference at(size_type pos) const noexcept {
50     if (pos >= size()) throw std::out_of_range{"pos is out of range"};
51     return data_[pos];
52   }
53 
operator [](size_type pos)54   reference operator[](size_type pos) noexcept { return data_[pos]; }
operator [](size_type pos) const55   const_reference operator[](size_type pos) const noexcept { return data_[pos]; }
56 
front()57   reference front() noexcept { return data_[0]; }
front() const58   const_reference front() const noexcept { return data_[0]; }
59 
back()60   reference back() noexcept { return data_[size_ - 1]; }
back() const61   const_reference back() const noexcept { return data_[size_ - 1]; }
62 
data()63   pointer data() noexcept { return static_cast<pointer>(data_); }
data() const64   const_pointer data() const noexcept { return static_cast<const_pointer>(data_); }
65 
begin()66   iterator begin() noexcept { return data_; }
begin() const67   const_iterator begin() const noexcept { return data_; }
68 
end()69   iterator end() noexcept { return begin() + size_; }
end() const70   const_iterator end() const noexcept { return begin() + size_; }
71 
cbegin()72   const_iterator cbegin() noexcept { return data_; }
cbegin() const73   const_iterator cbegin() const noexcept { return data_; }
74 
cend()75   const_iterator cend() noexcept { return cbegin() + size_; }
cend() const76   const_iterator cend() const noexcept { return cbegin() + size_; }
77 
max_size() const78   constexpr size_type max_size() const noexcept { return N; }
size() const79   size_type size() const noexcept { return size_; }
empty() const80   bool empty() const noexcept { return size_ == 0; }
81 
fill(const_reference value)82   void fill(const_reference value) noexcept(
83       std::is_nothrow_assignable<T, const_reference>::value) {
84     std::fill(begin(), end(), value);
85   }
86 
swap(sub_array & other)87   void swap(sub_array& other) noexcept(swap_element_is_noexcept()) {
88     using std::swap;
89     for (auto i = begin(), j = other.begin(); i != end(); ++i, ++j) swap(*i, *j);
90   }
91 
92 private:
93   size_type size_ = 0;
94   value_type data_[N];
95 };
96 
97 template <class T, std::size_t N>
operator ==(const sub_array<T,N> & a,const sub_array<T,N> & b)98 bool operator==(const sub_array<T, N>& a, const sub_array<T, N>& b) noexcept {
99   return std::equal(a.begin(), a.end(), b.begin());
100 }
101 
102 template <class T, std::size_t N>
operator !=(const sub_array<T,N> & a,const sub_array<T,N> & b)103 bool operator!=(const sub_array<T, N>& a, const sub_array<T, N>& b) noexcept {
104   return !(a == b);
105 }
106 
107 } // namespace detail
108 } // namespace histogram
109 } // namespace boost
110 
111 namespace std {
112 template <class T, std::size_t N>
swap(::boost::histogram::detail::sub_array<T,N> & a,::boost::histogram::detail::sub_array<T,N> & b)113 void swap(::boost::histogram::detail::sub_array<T, N>& a,
114           ::boost::histogram::detail::sub_array<T, N>& b) noexcept(noexcept(a.swap(b))) {
115   a.swap(b);
116 }
117 } // namespace std
118 
119 #endif
120