/* * fixed_size_vector.h */ #ifndef FIXED_SIZE_VECTOR_H #define FIXED_SIZE_VECTOR_H #include #include #include #include template struct fixed_size_vector { // Types using value_type = T; using reference = value_type&; using const_reference = const value_type&; using pointer = value_type*; using const_pointer = const value_type*; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using iterator = value_type*; using const_iterator = const value_type*; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; T elems_[N ? N : 1]; // Support for zero-sized fixed_size_vectors // No explicit construct/copy/destroy for aggregate type void fill(const T& u) { std::fill_n(begin(), size(), u); } void swap(fixed_size_vector& other) // Not available in gcc 4.7: noexcept(noexcept(swap(declval(), declval()))) { std::swap_ranges(begin(), end(), other.begin()); } // Iterators iterator begin() noexcept { return iterator(&elems_[0]); } const_iterator begin() const noexcept { return const_iterator(&elems_[0]); } iterator end() noexcept { return iterator(&elems_[N]); } const_iterator end() const noexcept { return const_iterator(&elems_[N]); } reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } reverse_iterator rend() noexcept { return reverse_iterator(begin()); } const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } const_iterator cbegin() noexcept { return const_iterator(begin()); } const_iterator cend() noexcept { return const_iterator(end()); } const_reverse_iterator crbegin() noexcept { return const_reverse_iterator(end()); } const_reverse_iterator crend() noexcept { return const_reverse_iterator(begin()); } // Capacity size_type size() const noexcept { return N; } size_type max_size() const noexcept { return N; } bool empty() const noexcept { return size() == 0; } // Element access reference operator[](size_type n) { return elems_[n]; } const_reference operator[](size_type n) const { return elems_[n]; } reference at(size_type n) { check_(n); return elems_[n]; } const_reference at(size_type n) const { check_(n); return elems_[n]; } reference front() { return *begin(); } const_reference front() const { return *begin(); } reference back() { return N ? *(end() - 1) : *end(); } const_reference back() const { return N ? *(end() - 1) : *end(); } pointer data() noexcept { return &elems_[0]; } const_pointer data() const noexcept { return &elems_[0]; } private: template void check_(size_type n) const { if (!(0 <= n && n < M)) throw std::out_of_range("fixed_size_vector check"); } }; template void swap(fixed_size_vector& x, fixed_size_vector& y) { std::swap_ranges(x.begin(), x.end(), y.begin()); } template bool operator==(const fixed_size_vector& lhs, const fixed_size_vector& rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } template bool operator!=(const fixed_size_vector& lhs, const fixed_size_vector& rhs) { return !(lhs == rhs); } template bool operator<(const fixed_size_vector& lhs, const fixed_size_vector& rhs) { return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } template bool operator>(const fixed_size_vector& lhs, const fixed_size_vector& rhs) { return rhs < lhs; } template bool operator<=(const fixed_size_vector& lhs, const fixed_size_vector& rhs) { return !(lhs > rhs); } template bool operator>=(const fixed_size_vector& lhs, const fixed_size_vector& rhs) { return !(lhs < rhs); } #endif