Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:36:26

0001 #ifndef FWCore_Utilities_VecArray_h
0002 #define FWCore_Utilities_VecArray_h
0003 
0004 #include <utility>
0005 #include <stdexcept>
0006 #include <string>
0007 #include <cstddef>
0008 
0009 namespace edm {
0010   /**
0011    * A class for extending std::array with std::vector-like interface.
0012    *
0013    * This class can be useful if the maximum length is known at
0014    * compile-time (can use std::array), and that the length is rather
0015    * small (maximum size of std::array is comparable with the overhead
0016    * of std::vector). It is also free of dynamic memory allocations.
0017    *
0018    * Note that the implemented interface is not complete compared to
0019    * std::array or std:vector. Feel free contribute if further needs
0020    * arise.
0021    *
0022    * The second template argument is unsigned int (not size_t) on
0023    * purpose to reduce the size of the class by 4 bytes (at least in
0024    * Linux amd64). For all practical purposes even unsigned char could
0025    * be enough.
0026    */
0027   template <typename T, unsigned int N>
0028   class VecArray {
0029     T data_[N];
0030     unsigned int size_;
0031 
0032   public:
0033     using value_type = T;
0034     using size_type = unsigned int;
0035     using difference_type = std::ptrdiff_t;
0036     using reference = value_type&;
0037     using const_reference = const value_type&;
0038     using pointer = value_type*;
0039     using const_pointer = const value_type*;
0040     using iterator = value_type*;
0041     using const_iterator = const value_type*;
0042 
0043     VecArray() : data_{}, size_{0} {}
0044 
0045     // Not range-checked, undefined behaviour if access beyond size()
0046     reference operator[](size_type pos) { return data_[pos]; }
0047     // Not range-checked, undefined behaviour if access beyond size()
0048     const_reference operator[](size_type pos) const { return data_[pos]; }
0049     // Undefined behaviour if size()==0
0050     reference front() { return data_[0]; }
0051     // Undefined behaviour if size()==0
0052     const_reference front() const { return data_[0]; }
0053 
0054     // Undefined behaviour if size()==0
0055     reference back() { return data_[size_ - 1]; }
0056     // Undefined behaviour if size()==0
0057     const_reference back() const { return data_[size_ - 1]; }
0058     pointer data() { return data_; }
0059     const_pointer data() const { return data_; }
0060 
0061     iterator begin() noexcept { return data_; }
0062     const_iterator begin() const noexcept { return data_; }
0063     const_iterator cbegin() const noexcept { return data_; }
0064 
0065     iterator end() noexcept { return begin() + size_; }
0066     const_iterator end() const noexcept { return begin() + size_; }
0067     const_iterator cend() const noexcept { return cbegin() + size_; }
0068 
0069     constexpr bool empty() const noexcept { return size_ == 0; }
0070     constexpr size_type size() const noexcept { return size_; }
0071     static constexpr size_type capacity() noexcept { return N; }
0072 
0073     void clear() { size_ = 0; }
0074 
0075     // Throws if size()==N
0076     void push_back(const T& value) {
0077       if (size_ >= N)
0078         throw std::length_error("push_back on already-full VecArray (N=" + std::to_string(N) + ")");
0079       push_back_unchecked(value);
0080     }
0081 
0082     // Undefined behaviour if size()==N
0083     void push_back_unchecked(const T& value) {
0084       data_[size_] = value;
0085       ++size_;
0086     }
0087 
0088     // Throws if size()==N
0089     template <typename... Args>
0090     void emplace_back(Args&&... args) {
0091       if (size_ >= N)
0092         throw std::length_error("emplace_back on already-full VecArray (N=" + std::to_string(N) + ")");
0093       emplace_back_unchecked(std::forward<Args>(args)...);
0094     }
0095 
0096     // Undefined behaviour if size()==N
0097     template <typename... Args>
0098     void emplace_back_unchecked(Args&&... args) {
0099       data_[size_] = T(std::forward<Args>(args)...);
0100       ++size_;
0101     }
0102 
0103     // Undefined behaviour if size()==0
0104     void pop_back() { --size_; }
0105 
0106     void resize(unsigned int size) {
0107       if (size > N)
0108         throw std::length_error("Requesting size " + std::to_string(size) + " while maximum allowed is " +
0109                                 std::to_string(N));
0110 
0111       while (size < size_)
0112         pop_back();
0113       size_ = size;
0114     }
0115 
0116     void swap(VecArray& other) noexcept(noexcept(std::swap(data_, other.data_)) &&
0117                                         noexcept(std::swap(size_, other.size_))) {
0118       std::swap(data_, other.data_);
0119       std::swap(size_, other.size_);
0120     }
0121   };
0122 }  // namespace edm
0123 
0124 #endif