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