|
|
@ -30,19 +30,12 @@ public:
|
|
|
|
using value_type = T;
|
|
|
|
using value_type = T;
|
|
|
|
|
|
|
|
|
|
|
|
bounded_vector() = default;
|
|
|
|
bounded_vector() = default;
|
|
|
|
template <typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0>
|
|
|
|
explicit bounded_vector(size_type N) { append(N); }
|
|
|
|
explicit bounded_vector(size_type N)
|
|
|
|
bounded_vector(size_type N, const T& val) { append(N, val); }
|
|
|
|
{
|
|
|
|
|
|
|
|
append(N);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename U, typename std::enable_if<std::is_constructible<T, const U&>::value, int>::type = 0>
|
|
|
|
|
|
|
|
bounded_vector(size_type N, const U& init_val)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
append(N, T(init_val));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bounded_vector(const bounded_vector& other) { append(other.begin(), other.end()); }
|
|
|
|
bounded_vector(const bounded_vector& other) { append(other.begin(), other.end()); }
|
|
|
|
bounded_vector(bounded_vector&& other) noexcept
|
|
|
|
bounded_vector(bounded_vector&& other) noexcept
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_move_constructible<T>::value, "T must be move-constructible");
|
|
|
|
std::uninitialized_copy(std::make_move_iterator(other.begin()), std::make_move_iterator(other.end()), end());
|
|
|
|
std::uninitialized_copy(std::make_move_iterator(other.begin()), std::make_move_iterator(other.end()), end());
|
|
|
|
size_ = other.size();
|
|
|
|
size_ = other.size();
|
|
|
|
other.clear();
|
|
|
|
other.clear();
|
|
|
@ -114,13 +107,13 @@ public:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
T& front() { return (*this)[0]; }
|
|
|
|
T& front() { return (*this)[0]; }
|
|
|
|
const T& front() const { return (*this)[0]; }
|
|
|
|
const T& front() const { return (*this)[0]; }
|
|
|
|
T* data() { return reinterpret_cast<T*>(&buffer[0]); }
|
|
|
|
T* data() { return &front(); }
|
|
|
|
const T* data() const { return reinterpret_cast<T*>(&buffer[0]); }
|
|
|
|
const T* data() const { return &front(); }
|
|
|
|
|
|
|
|
|
|
|
|
// Iterators
|
|
|
|
// Iterators
|
|
|
|
iterator begin() { return reinterpret_cast<iterator>(&buffer[0]); }
|
|
|
|
iterator begin() { return data(); }
|
|
|
|
iterator end() { return begin() + size_; }
|
|
|
|
iterator end() { return begin() + size_; }
|
|
|
|
const_iterator begin() const { return reinterpret_cast<const_iterator>(&buffer[0]); }
|
|
|
|
const_iterator begin() const { return data(); }
|
|
|
|
const_iterator end() const { return begin() + size_; }
|
|
|
|
const_iterator end() const { return begin() + size_; }
|
|
|
|
|
|
|
|
|
|
|
|
// Capacity
|
|
|
|
// Capacity
|
|
|
@ -159,19 +152,22 @@ public:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void push_back(const T& value)
|
|
|
|
void push_back(const T& value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_copy_constructible<T>::value, "T must be copy-constructible");
|
|
|
|
size_++;
|
|
|
|
size_++;
|
|
|
|
assert(size_ <= MAX_N);
|
|
|
|
assert(size_ <= MAX_N);
|
|
|
|
new (&back()) T(value);
|
|
|
|
new (&back()) T(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void push_back(T&& value)
|
|
|
|
void push_back(T&& value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_move_constructible<T>::value, "T must be move-constructible");
|
|
|
|
size_++;
|
|
|
|
size_++;
|
|
|
|
assert(size_ <= MAX_N);
|
|
|
|
assert(size_ <= MAX_N);
|
|
|
|
new (&back()) T(std::move(value));
|
|
|
|
new (&back()) T(std::move(value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template <typename... Args>
|
|
|
|
template <typename... Args>
|
|
|
|
typename std::enable_if<std::is_constructible<T, Args...>::value>::type emplace_back(Args&&... args)
|
|
|
|
void emplace_back(Args&&... args)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_constructible<T, Args&&...>::value, "Passed arguments to emplace_back are invalid");
|
|
|
|
size_++;
|
|
|
|
size_++;
|
|
|
|
assert(size_ <= MAX_N);
|
|
|
|
assert(size_ <= MAX_N);
|
|
|
|
new (&back()) T(std::forward<Args>(args)...);
|
|
|
|
new (&back()) T(std::forward<Args>(args)...);
|
|
|
@ -182,9 +178,14 @@ public:
|
|
|
|
back().~T();
|
|
|
|
back().~T();
|
|
|
|
size_--;
|
|
|
|
size_--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
typename std::enable_if<std::is_default_constructible<T>::value>::type resize(size_type count) { resize(count, T()); }
|
|
|
|
void resize(size_type count)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_default_constructible<T>::value, "T must be default constructible");
|
|
|
|
|
|
|
|
resize(count, T());
|
|
|
|
|
|
|
|
}
|
|
|
|
void resize(size_type count, const T& value)
|
|
|
|
void resize(size_type count, const T& value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
|
|
|
|
if (size_ > count) {
|
|
|
|
if (size_ > count) {
|
|
|
|
destroy(begin() + count, end());
|
|
|
|
destroy(begin() + count, end());
|
|
|
|
size_ = count;
|
|
|
|
size_ = count;
|
|
|
@ -215,12 +216,14 @@ private:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void append(size_type N, const T& element)
|
|
|
|
void append(size_type N, const T& element)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_copy_constructible<T>::value, "T must be copy-constructible");
|
|
|
|
assert(N + size_ <= MAX_N);
|
|
|
|
assert(N + size_ <= MAX_N);
|
|
|
|
std::uninitialized_fill_n(end(), N, element);
|
|
|
|
std::uninitialized_fill_n(end(), N, element);
|
|
|
|
size_ += N;
|
|
|
|
size_ += N;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void append(size_type N)
|
|
|
|
void append(size_type N)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
static_assert(std::is_default_constructible<T>::value, "T must be default-constructible");
|
|
|
|
assert(N + size_ <= MAX_N);
|
|
|
|
assert(N + size_ <= MAX_N);
|
|
|
|
for (size_type i = size_; i < size_ + N; ++i) {
|
|
|
|
for (size_type i = size_; i < size_ + N; ++i) {
|
|
|
|
new (&buffer[i]) T();
|
|
|
|
new (&buffer[i]) T();
|
|
|
|