Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:47

0001 // Copyright 2019 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_DETAIL_SUB_ARRAY_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_SUB_ARRAY_HPP
0009 
0010 #include <algorithm>
0011 #include <boost/throw_exception.hpp>
0012 #include <stdexcept>
0013 
0014 namespace boost {
0015 namespace histogram {
0016 namespace detail {
0017 
0018 // Like std::array, but allows to use less than maximum capacity.
0019 // Cannot inherit from std::array, since this confuses span.
0020 template <class T, std::size_t N>
0021 class sub_array {
0022   static constexpr bool swap_element_is_noexcept() noexcept {
0023     using std::swap;
0024     return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
0025   }
0026 
0027 public:
0028   using element_type = T;
0029   using size_type = std::size_t;
0030   using reference = T&;
0031   using const_reference = const T&;
0032   using pointer = T*;
0033   using const_pointer = const T*;
0034   using iterator = pointer;
0035   using const_iterator = const_pointer;
0036 
0037   sub_array() = default;
0038 
0039   explicit sub_array(std::size_t s) noexcept : size_(s) { assert(size_ <= N); }
0040 
0041   sub_array(std::size_t s, const T& value) noexcept(
0042       std::is_nothrow_assignable<T, const_reference>::value)
0043       : sub_array(s) {
0044     fill(value);
0045   }
0046 
0047   sub_array(std::initializer_list<T> il) noexcept(
0048       std::is_nothrow_assignable<T, const_reference>::value)
0049       : sub_array(il.size()) {
0050     std::copy(il.begin(), il.end(), data_);
0051   }
0052 
0053   reference at(size_type pos) noexcept {
0054     if (pos >= size()) BOOST_THROW_EXCEPTION(std::out_of_range{"pos is out of range"});
0055     return data_[pos];
0056   }
0057 
0058   const_reference at(size_type pos) const noexcept {
0059     if (pos >= size()) BOOST_THROW_EXCEPTION(std::out_of_range{"pos is out of range"});
0060     return data_[pos];
0061   }
0062 
0063   reference operator[](size_type pos) noexcept { return data_[pos]; }
0064   const_reference operator[](size_type pos) const noexcept { return data_[pos]; }
0065 
0066   reference front() noexcept { return data_[0]; }
0067   const_reference front() const noexcept { return data_[0]; }
0068 
0069   reference back() noexcept { return data_[size_ - 1]; }
0070   const_reference back() const noexcept { return data_[size_ - 1]; }
0071 
0072   pointer data() noexcept { return static_cast<pointer>(data_); }
0073   const_pointer data() const noexcept { return static_cast<const_pointer>(data_); }
0074 
0075   iterator begin() noexcept { return data_; }
0076   const_iterator begin() const noexcept { return data_; }
0077 
0078   iterator end() noexcept { return begin() + size_; }
0079   const_iterator end() const noexcept { return begin() + size_; }
0080 
0081   const_iterator cbegin() const noexcept { return data_; }
0082   const_iterator cend() const noexcept { return cbegin() + size_; }
0083 
0084   constexpr size_type max_size() const noexcept { return N; }
0085   size_type size() const noexcept { return size_; }
0086   bool empty() const noexcept { return size_ == 0; }
0087 
0088   void fill(const_reference value) noexcept(
0089       std::is_nothrow_assignable<T, const_reference>::value) {
0090     std::fill(begin(), end(), value);
0091   }
0092 
0093   void swap(sub_array& other) noexcept(swap_element_is_noexcept()) {
0094     using std::swap;
0095     const size_type s = (std::max)(size(), other.size());
0096     for (auto i = begin(), j = other.begin(), end = begin() + s; i != end; ++i, ++j)
0097       swap(*i, *j);
0098     swap(size_, other.size_);
0099   }
0100 
0101 private:
0102   size_type size_ = 0;
0103   element_type data_[N];
0104 };
0105 
0106 template <class T, std::size_t N>
0107 bool operator==(const sub_array<T, N>& a, const sub_array<T, N>& b) noexcept {
0108   return std::equal(a.begin(), a.end(), b.begin(), b.end());
0109 }
0110 
0111 template <class T, std::size_t N>
0112 bool operator!=(const sub_array<T, N>& a, const sub_array<T, N>& b) noexcept {
0113   return !(a == b);
0114 }
0115 
0116 } // namespace detail
0117 } // namespace histogram
0118 } // namespace boost
0119 
0120 namespace std {
0121 template <class T, std::size_t N>
0122 void swap(::boost::histogram::detail::sub_array<T, N>& a,
0123           ::boost::histogram::detail::sub_array<T, N>& b) noexcept(noexcept(a.swap(b))) {
0124   a.swap(b);
0125 }
0126 } // namespace std
0127 
0128 #endif