1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
|
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
#ifndef DUNE_FUNCTIONS_COMMON_OVERFLOWARRAY_HH
#define DUNE_FUNCTIONS_COMMON_OVERFLOWARRAY_HH
#include <algorithm>
#include <iostream>
#include <cstddef>
#include <array>
#include <initializer_list>
#include <dune/common/genericiterator.hh>
namespace Dune::Functions {
/**
* \brief A dynamically sized array-like class with overflow
*
* \tparam BA Type of base array
* \tparam maxSize Maximal size of OverflowArray
*
* This class publicly inherits from a statically sized array-like
* base class BA and extends it by an overflow such that
* a total capacity of maxSize is available. Within this bound
* the size is managed dynamically.
*
* Potential usecase: If you want to construct a statically
* sized array but need dynamic resizing while building it,
* you can use an OverflowArray<std::array<T,finalSize>, ...>
* and cast the result to the base class type.
*
* Similar to Dune::ReservedVector this uses a std::array
* internally with the following implications: Entries must be
* default-constructible. The whole capacity will always be filled
* with entries, even if size<capacity. Entries are only destructed
* when the OverflowArray is destructed - not when shrinking
* or clearing it.
*/
template<class BA, std::size_t maxSize = std::tuple_size_v<BA>>
class OverflowArray :
public BA
{
static constexpr std::size_t baseSize = std::tuple_size_v<BA>;
public:
using BaseArray = BA;
using value_type = typename BaseArray::value_type;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
using iterator = Dune::GenericIterator<OverflowArray, value_type>;
using const_iterator = Dune::GenericIterator<const OverflowArray, const value_type>;
private:
using OverflowBuffer = std::array<value_type, maxSize-baseSize>;
public:
OverflowArray() = default;
OverflowArray(const std::initializer_list<value_type>& l) {
assert(l.size() <= capacity());
size_ = l.size();
std::copy_n(l.begin(), size_, begin());
}
bool operator == (const OverflowArray& other) const {
if (size() != other.size())
return false;
for (size_type i=0; i<size(); ++i)
if ((*this)[i] != other[i])
return false;
return true;
}
//! Erases all elements.
void clear() {
size_ = 0;
}
/**
* \brief Specifies a new size for the OverflowArray.
*
* The new size must not exceed max_size().
* This is an O(1) operation.
*/
void resize(size_type n) {
assert(n <= capacity());
size_ = n;
}
/**
* \brief Appends an element to the end of the OverflowArray,
*
* The new size must not exceed max_size().
* This is an O(1) operation.
*/
void push_back(const value_type& t) {
assert(size() < capacity());
(*this)[size_++] = t;
}
//! Erases the last element of the OverflowArray, O(1) time.
void pop_back() {
assert(size() > 0);
if (! empty())
size_--;
}
/**
* \brief Inserts an element to the begin of the OverflowArray,
*
* The new size must not exceed max_size().
* This is an O(size()) operation.
*/
void push_front(const value_type& t) {
assert(size() < capacity());
for (size_type i=0; i<size(); i++)
(*this)[i+1] = (*this)[i];
(*this)[0] = t;
}
//! Returns a iterator pointing to the beginning of the OverflowArray.
iterator begin() {
return iterator(*this, 0);
}
//! Returns a const_iterator pointing to the beginning of the OverflowArray.
const_iterator begin() const {
return const_iterator(*this, 0);
}
//! Returns an iterator pointing to the end of the OverflowArray.
iterator end() {
return iterator(*this, size());
}
//! Returns a const_iterator pointing to the end of the OverflowArray.
const_iterator end() const {
return const_iterator(*this, size());
}
//! Returns reference to the i'th element.
reference operator[] (size_type i) {
assert(i < size());
// If there's no padding between the base class and the overflow_ member,
// the compiler should be able to optimize this to
// return *(&BaseArray::operator[](0) + i);
if (i<baseSize)
return BaseArray::operator[](i);
return overflow_[i-baseSize];
}
//! Returns a const reference to the i'th element.
const_reference operator[] (size_type i) const {
assert(i < size());
// If there's no padding between the base class and the overflow_ member,
// the compiler should be able to optimize this to
// return *(&BaseArray::operator[](0) + i);
if (i<baseSize)
return BaseArray::operator[](i);
return overflow_[i-baseSize];
}
//! Returns reference to first element of OverflowArray.
reference front() {
assert(size() > 0);
return (*this)[0];
}
//! Returns const reference to first element of OverflowArray.
const_reference front() const {
assert(size() > 0);
return (*this)[0];
}
//! Returns reference to last element of OverflowArray.
reference back() {
assert(size() > 0);
return (*this)[size()-1];
}
//! Returns const reference to last element of OverflowArray.
const_reference back() const {
assert(size() > 0);
return (*this)[size()-1];
}
//! Returns number of elements in the OverflowArray.
size_type size () const {
return size_;
}
//! Returns true if OverflowArray has no elements.
bool empty() const {
return size() == 0;
}
//! Returns the capacity of the OverflowArray.
static constexpr size_type capacity() {
return maxSize;
}
//! Returns the maximum length of the OverflowArray.
static constexpr size_type max_size() {
return maxSize;
}
//! Compute hash value
inline friend std::size_t hash_value(const OverflowArray& v) noexcept {
return hash_range(v.begin(), v.end());
}
//! Write container to an output stream
friend std::ostream& operator<< (std::ostream& s, const OverflowArray& c) {
for (const auto& ci : c)
s << ci << " ";
return s;
}
private:
OverflowBuffer overflow_;
size_type size_ = 0;
};
} // namespace Dune::Functions
#endif // DUNE_FUNCTIONS_COMMON_OVERFLOWARRAY_HH
|