...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
boost::histogram::unlimited_storage — Memory-efficient storage for integral counters which cannot overflow.
// In header: <boost/histogram/unlimited_storage.hpp> template<typename Allocator> class unlimited_storage { public: // types typedef unspecified const_reference; typedef unspecified reference; typedef Allocator allocator_type; typedef double value_type; typedef unspecified large_int; typedef unspecified const_iterator; typedef unspecified iterator; // construct/copy/destruct explicit unlimited_storage(const allocator_type & = {}); unlimited_storage(const unlimited_storage &) = default; unlimited_storage(unlimited_storage &&) = default; template<typename Iterable> explicit unlimited_storage(const Iterable &); unlimited_storage & operator=(const unlimited_storage &) = default; unlimited_storage & operator=(unlimited_storage &&) = default; template<typename Iterable> unlimited_storage & operator=(const Iterable &); // public member functions allocator_type get_allocator() const; void reset(std::size_t); std::size_t size() const noexcept; reference operator[](std::size_t) noexcept; const_reference operator[](std::size_t) const noexcept; bool operator==(const unlimited_storage &) const noexcept; template<typename Iterable> bool operator==(const Iterable &) const; unlimited_storage & operator *=(const double); iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; template<typename Archive> void serialize(Archive &, unsigned); // public data members static constexpr bool has_threading_support; };
This storage provides a no-overflow-guarantee if the counters are incremented with integer weights. It maintains a contiguous array of elemental counters, one for each cell. If an operation is requested which would overflow a counter, the array is replaced with another of a wider integral type, then the operation is executed. The storage uses integers of 8, 16, 32, 64 bits, and then switches to a multiprecision integral type, similar to those in Boost.Multiprecision.
A scaling operation or adding a floating point number triggers a conversion of the elemental counters into doubles, which voids the no-overflow-guarantee.
unlimited_storage
public
construct/copy/destructexplicit unlimited_storage(const allocator_type & a = {});
unlimited_storage(const unlimited_storage &) = default;
unlimited_storage(unlimited_storage &&) = default;
template<typename Iterable> explicit unlimited_storage(const Iterable & s);
unlimited_storage & operator=(const unlimited_storage &) = default;
unlimited_storage & operator=(unlimited_storage &&) = default;
template<typename Iterable> unlimited_storage & operator=(const Iterable & s);
unlimited_storage
public member functionsallocator_type get_allocator() const;
void reset(std::size_t n);
std::size_t size() const noexcept;
reference operator[](std::size_t i) noexcept;
const_reference operator[](std::size_t i) const noexcept;
bool operator==(const unlimited_storage & x) const noexcept;
template<typename Iterable> bool operator==(const Iterable & iterable) const;
unlimited_storage & operator *=(const double x);
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
template<typename Archive> void serialize(Archive & ar, unsigned);