static_vector.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. #ifndef BOOST_HISTOGRAM_DETAIL_STATIC_VECTOR_HPP
  7. #define BOOST_HISTOGRAM_DETAIL_STATIC_VECTOR_HPP
  8. #include <algorithm>
  9. #include <boost/throw_exception.hpp>
  10. #include <stdexcept>
  11. namespace boost {
  12. namespace histogram {
  13. namespace detail {
  14. // A crude implementation of boost::container::static_vector.
  15. // Like std::vector, but with static allocation up to a maximum capacity.
  16. template <class T, std::size_t N>
  17. class static_vector {
  18. // Cannot inherit from std::array, since this confuses span.
  19. static constexpr bool swap_element_is_noexcept() noexcept {
  20. using std::swap;
  21. return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
  22. }
  23. public:
  24. using element_type = T;
  25. using size_type = std::size_t;
  26. using reference = T&;
  27. using const_reference = const T&;
  28. using pointer = T*;
  29. using const_pointer = const T*;
  30. using iterator = pointer;
  31. using const_iterator = const_pointer;
  32. static_vector() = default;
  33. explicit static_vector(std::size_t s) noexcept : size_(s) { assert(size_ <= N); }
  34. static_vector(std::size_t s, const T& value) noexcept(
  35. std::is_nothrow_assignable<T, const_reference>::value)
  36. : static_vector(s) {
  37. fill(value);
  38. }
  39. static_vector(std::initializer_list<T> il) noexcept(
  40. std::is_nothrow_assignable<T, const_reference>::value)
  41. : static_vector(il.size()) {
  42. std::copy(il.begin(), il.end(), data_);
  43. }
  44. reference at(size_type pos) noexcept {
  45. if (pos >= size()) BOOST_THROW_EXCEPTION(std::out_of_range{"pos is out of range"});
  46. return data_[pos];
  47. }
  48. const_reference at(size_type pos) const noexcept {
  49. if (pos >= size()) BOOST_THROW_EXCEPTION(std::out_of_range{"pos is out of range"});
  50. return data_[pos];
  51. }
  52. reference operator[](size_type pos) noexcept { return data_[pos]; }
  53. const_reference operator[](size_type pos) const noexcept { return data_[pos]; }
  54. reference front() noexcept { return data_[0]; }
  55. const_reference front() const noexcept { return data_[0]; }
  56. reference back() noexcept { return data_[size_ - 1]; }
  57. const_reference back() const noexcept { return data_[size_ - 1]; }
  58. pointer data() noexcept { return static_cast<pointer>(data_); }
  59. const_pointer data() const noexcept { return static_cast<const_pointer>(data_); }
  60. iterator begin() noexcept { return data_; }
  61. const_iterator begin() const noexcept { return data_; }
  62. iterator end() noexcept { return begin() + size_; }
  63. const_iterator end() const noexcept { return begin() + size_; }
  64. const_iterator cbegin() const noexcept { return data_; }
  65. const_iterator cend() const noexcept { return cbegin() + size_; }
  66. constexpr size_type max_size() const noexcept { return N; }
  67. size_type size() const noexcept { return size_; }
  68. bool empty() const noexcept { return size_ == 0; }
  69. void fill(const_reference value) noexcept(
  70. std::is_nothrow_assignable<T, const_reference>::value) {
  71. std::fill(begin(), end(), value);
  72. }
  73. void swap(static_vector& other) noexcept(swap_element_is_noexcept()) {
  74. using std::swap;
  75. const size_type s = (std::max)(size(), other.size());
  76. for (auto i = begin(), j = other.begin(), end = begin() + s; i != end; ++i, ++j)
  77. swap(*i, *j);
  78. swap(size_, other.size_);
  79. }
  80. private:
  81. size_type size_ = 0;
  82. element_type data_[N];
  83. };
  84. template <class T, std::size_t N>
  85. bool operator==(const static_vector<T, N>& a, const static_vector<T, N>& b) noexcept {
  86. return std::equal(a.begin(), a.end(), b.begin(), b.end());
  87. }
  88. template <class T, std::size_t N>
  89. bool operator!=(const static_vector<T, N>& a, const static_vector<T, N>& b) noexcept {
  90. return !(a == b);
  91. }
  92. } // namespace detail
  93. } // namespace histogram
  94. } // namespace boost
  95. namespace std {
  96. template <class T, std::size_t N>
  97. void swap(
  98. ::boost::histogram::detail::static_vector<T, N>& a,
  99. ::boost::histogram::detail::static_vector<T, N>& b) noexcept(noexcept(a.swap(b))) {
  100. a.swap(b);
  101. }
  102. } // namespace std
  103. #endif