collector.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright 2024 Ruggero Turra, 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_ACCUMULATORS_COLLECTOR_HPP
  7. #define BOOST_HISTOGRAM_ACCUMULATORS_COLLECTOR_HPP
  8. #include <algorithm> // for std::equal
  9. #include <boost/core/nvp.hpp>
  10. #include <boost/histogram/detail/detect.hpp>
  11. #include <boost/histogram/fwd.hpp> // for collector<>
  12. #include <initializer_list>
  13. #include <type_traits>
  14. namespace boost {
  15. namespace histogram {
  16. namespace accumulators {
  17. /** Collects samples.
  18. Input samples are stored in an internal container for later retrival, which stores the
  19. values consecutively in memory. The interface is designed to work with std::vector and
  20. other containers which implement the same API.
  21. Warning: The memory of the accumulator is unbounded.
  22. */
  23. template <class ContainerType>
  24. class collector {
  25. public:
  26. using container_type = ContainerType;
  27. using value_type = typename container_type::value_type;
  28. using allocator_type = typename container_type::allocator_type;
  29. using const_reference = typename container_type::const_reference;
  30. using iterator = typename container_type::iterator;
  31. using const_iterator = typename container_type::const_iterator;
  32. using size_type = typename container_type::size_type;
  33. using const_pointer = typename container_type::const_pointer;
  34. // make template only match if forwarding args to container is valid
  35. template <typename... Args, class = decltype(container_type(std::declval<Args>()...))>
  36. explicit collector(Args&&... args) : container_(std::forward<Args>(args)...) {}
  37. // make template only match if forwarding args to container is valid
  38. template <class T, typename... Args, class = decltype(container_type(std::initializer_list<T>(),std::declval<Args>()...))>
  39. explicit collector(std::initializer_list<T> list, Args&&... args)
  40. : container_(list, std::forward<Args>(args)...) {}
  41. /// Append sample x.
  42. void operator()(const_reference x) { container_.push_back(x); }
  43. /// Append samples from another collector.
  44. template <class C>
  45. collector& operator+=(const collector<C>& rhs) {
  46. container_.reserve(size() + rhs.size());
  47. container_.insert(end(), rhs.begin(), rhs.end());
  48. return *this;
  49. }
  50. /// Return true if collections are equal.
  51. ///
  52. /// Two collections are equal if they have the same number of elements
  53. /// which all compare equal.
  54. template <class Iterable, class = detail::is_iterable<Iterable>>
  55. bool operator==(const Iterable& rhs) const noexcept {
  56. return std::equal(begin(), end(), rhs.begin(), rhs.end());
  57. }
  58. /// Return true if collections are not equal.
  59. template <class Iterable, class = detail::is_iterable<Iterable>>
  60. bool operator!=(const Iterable& rhs) const noexcept {
  61. return !operator==(rhs);
  62. }
  63. /// Return number of samples.
  64. size_type size() const noexcept { return container_.size(); }
  65. /// Return number of samples (alias for size()).
  66. size_type count() const noexcept { return container_.size(); }
  67. /// Return readonly iterator to start of collection.
  68. const const_iterator begin() const noexcept { return container_.begin(); }
  69. /// Return readonly iterator to end of collection.
  70. const const_iterator end() const noexcept { return container_.end(); }
  71. /// Return const reference to value at index.
  72. const_reference operator[](size_type idx) const noexcept { return container_[idx]; }
  73. /// Return pointer to internal memory.
  74. const_pointer data() const noexcept { return container_.data(); }
  75. allocator_type get_allocator() const { return container_.get_allocator(); }
  76. template <class Archive>
  77. void serialize(Archive& ar, unsigned version) {
  78. (void)version;
  79. ar& make_nvp("container", container_);
  80. }
  81. private:
  82. container_type container_;
  83. };
  84. } // namespace accumulators
  85. } // namespace histogram
  86. } // namespace boost
  87. #endif