mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
118db71121
This replaces the STL <new> header. Mainly, it defines a global operator new and operator delete, as well as the placement versions of these. The placement versions are required to not get compile errors when trying to write a placement new statement. Each of these operators is defined with many, many different variants. A glance at new.cc is recommended followed by a chaser of the Alexandrescu talk "std::allocator is to Allocation as std::vector is to Vexation". We must provide a global-namespace source-level definition of each operator and it is illegal for any of them to be marked inline, so here we are. The upshot is that we no longer need to include <new>, and our optional/ vector headers are self-contained.
247 lines
4.4 KiB
C++
247 lines
4.4 KiB
C++
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
|
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
|
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
|
#include "new.h"
|
|
#include <__utility/forward.h>
|
|
#include <__utility/move.h>
|
|
#include <__utility/swap.h>
|
|
|
|
namespace ctl {
|
|
|
|
template<typename T>
|
|
struct vector
|
|
{
|
|
size_t n = 0;
|
|
size_t c = 0;
|
|
T* p = nullptr;
|
|
|
|
using iterator = T*;
|
|
using const_iterator = const T*;
|
|
|
|
vector() = default;
|
|
|
|
~vector()
|
|
{
|
|
delete[] p;
|
|
}
|
|
|
|
vector(const vector& other)
|
|
{
|
|
n = other.n;
|
|
c = other.c;
|
|
p = new T[c];
|
|
for (size_t i = 0; i < n; ++i)
|
|
new (&p[i]) T(other.p[i]);
|
|
}
|
|
|
|
vector(vector&& other) noexcept
|
|
{
|
|
n = other.n;
|
|
c = other.c;
|
|
p = other.p;
|
|
other.n = 0;
|
|
other.c = 0;
|
|
other.p = nullptr;
|
|
}
|
|
|
|
explicit vector(size_t count, const T& value = T())
|
|
{
|
|
n = count;
|
|
c = count;
|
|
p = new T[c];
|
|
for (size_t i = 0; i < n; ++i)
|
|
new (&p[i]) T(value);
|
|
}
|
|
|
|
vector& operator=(const vector& other)
|
|
{
|
|
if (this != &other) {
|
|
T* newData = new T[other.c];
|
|
for (size_t i = 0; i < other.n; ++i) {
|
|
newData[i] = other.p[i];
|
|
}
|
|
delete[] p;
|
|
p = newData;
|
|
n = other.n;
|
|
c = other.c;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
vector& operator=(vector&& other) noexcept
|
|
{
|
|
if (this != &other) {
|
|
delete[] p;
|
|
p = other.p;
|
|
n = other.n;
|
|
c = other.c;
|
|
other.p = nullptr;
|
|
other.n = 0;
|
|
other.c = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool empty() const
|
|
{
|
|
return !n;
|
|
}
|
|
|
|
size_t size() const
|
|
{
|
|
return n;
|
|
}
|
|
|
|
size_t capacity() const
|
|
{
|
|
return c;
|
|
}
|
|
|
|
T& operator[](size_t i)
|
|
{
|
|
if (i >= n)
|
|
__builtin_trap();
|
|
return p[i];
|
|
}
|
|
|
|
const T& operator[](size_t i) const
|
|
{
|
|
if (i >= n)
|
|
__builtin_trap();
|
|
return p[i];
|
|
}
|
|
|
|
iterator begin()
|
|
{
|
|
return p;
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return p + n;
|
|
}
|
|
|
|
const_iterator cbegin() const
|
|
{
|
|
return p;
|
|
}
|
|
|
|
const_iterator cend() const
|
|
{
|
|
return p + n;
|
|
}
|
|
|
|
T& front()
|
|
{
|
|
if (!n)
|
|
__builtin_trap();
|
|
return p[0];
|
|
}
|
|
|
|
const T& front() const
|
|
{
|
|
if (!n)
|
|
__builtin_trap();
|
|
return p[0];
|
|
}
|
|
|
|
T& back()
|
|
{
|
|
if (!n)
|
|
__builtin_trap();
|
|
return p[n - 1];
|
|
}
|
|
|
|
const T& back() const
|
|
{
|
|
if (!n)
|
|
__builtin_trap();
|
|
return p[n - 1];
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
for (size_t i = 0; i < n; ++i)
|
|
p[i].~T();
|
|
n = 0;
|
|
}
|
|
|
|
void reserve(size_t c2)
|
|
{
|
|
if (c2 <= c)
|
|
return;
|
|
T* newP = new T[c2];
|
|
for (size_t i = 0; i < n; ++i)
|
|
newP[i] = std::move(p[i]);
|
|
delete[] p;
|
|
p = newP;
|
|
c = c2;
|
|
}
|
|
|
|
void push_back(const T& e)
|
|
{
|
|
if (n == c) {
|
|
size_t c2 = c + 1;
|
|
c2 += c2 >> 1;
|
|
reserve(c2);
|
|
}
|
|
new (&p[n]) T(e);
|
|
++n;
|
|
}
|
|
|
|
void push_back(T&& e)
|
|
{
|
|
if (n == c) {
|
|
size_t c2 = c + 1;
|
|
c2 += c2 >> 1;
|
|
reserve(c2);
|
|
}
|
|
new (&p[n]) T(std::forward<T>(e));
|
|
++n;
|
|
}
|
|
|
|
template<typename... Args>
|
|
void emplace_back(Args&&... args)
|
|
{
|
|
if (n == c) {
|
|
size_t c2 = c + 1;
|
|
c2 += c2 >> 1;
|
|
reserve(c2);
|
|
}
|
|
new (&p[n]) T(std::forward<Args>(args)...);
|
|
++n;
|
|
}
|
|
|
|
void pop_back()
|
|
{
|
|
if (n > 0) {
|
|
--n;
|
|
p[n].~T();
|
|
}
|
|
}
|
|
|
|
void resize(size_t n2)
|
|
{
|
|
if (n2 > n) {
|
|
reserve(n2);
|
|
for (size_t i = n; i < n2; ++i)
|
|
new (&p[i]) T();
|
|
} else if (n2 < n) {
|
|
for (size_t i = n2; i < n; ++i)
|
|
p[i].~T();
|
|
}
|
|
n = n2;
|
|
}
|
|
|
|
void swap(vector& other) noexcept
|
|
{
|
|
std::swap(n, other.n);
|
|
std::swap(c, other.c);
|
|
std::swap(p, other.p);
|
|
}
|
|
};
|
|
|
|
} // namespace ctl
|
|
|
|
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_
|