I am learning c++ and read why we can't use realloc() in std::vector, but i think we can use realloc() for pods, so here is my attempt to write std::vector like class template specialized for PODs
#include <malloc.h>
#include <stdexcept>
#include <type_traits>
namespace gupta {
namespace detail {
namespace podvector {
template <typename T> inline auto malloc(size_t elm_count) {
return ::malloc(elm_count * sizeof(T));
}
template <typename T> inline auto realloc(void *old_block, size_t elm_count) {
return ::realloc(old_block, elm_count * sizeof(T));
}
} // namespace podvector
} // namespace detail
template <typename PodType,
typename = std::enable_if_t<std::is_pod<PodType>::value>>
class podvector {
public:
using value_type = PodType;
using size_type = size_t;
using pointer = value_type *;
using const_value_pointer = const value_type *;
~podvector() {
if (m_memory)
free(m_memory);
}
podvector(size_type initial_size = 0) {
alloc(initial_size);
m_size = initial_size;
}
podvector(size_type initial_size, const value_type &value)
: podvector(initial_size) {
for (auto &v : *this)
v = value;
}
podvector(const podvector &other) : podvector(other.m_size) {
for (size_type i = 0; i < m_size; i++)
m_memory[i] = other.m_memory[i];
}
podvector(const podvector &&other)
: m_memory{std::move(other.m_memory)},
m_capacity{std::move(other.m_capacity)}, m_size{
std::move(other.m_size)} {
// other.m_memory = nullptr;
other.alloc(0);
}
podvector &operator=(const podvector &rhs) {
if (this != &rhs) {
resize(rhs.m_size);
for (size_type i = 0; i < rhs.m_size; i++)
m_memory[i] = rhs[i];
}
return *this;
}
podvector &operator=(podvector &&rhs) {
if (this != &rhs) {
this->~podvector();
m_memory = std::move(rhs.m_memory);
m_capacity = std::move(rhs.m_capacity);
m_size = std::move(rhs.m_size);
// rhs.m_memory = nullptr;
rhs.alloc(0);
}
return *this;
}
void resize(size_type new_size) {
if (new_size > m_size)
change_capacity(new_size);
m_size = new_size;
}
void reserve(size_type new_capacity) {
if (m_capacity < new_capacity)
change_capacity(new_capacity);
}
void push_back(const value_type &new_elm) {
if (m_size + 1 > m_capacity)
change_capacity(std::min(m_capacity * 2, 1));
m_memory[m_size++] = new_elm;
}
void pop_back() { m_size--; }
auto size() const { return m_size; }
auto capacity() const { return m_capacity; }
pointer begin() { return m_memory; }
const_value_pointer begin() const { return m_memory; }
pointer end() { return m_memory + m_size; }
const_value_pointer end() const { return m_memory + m_size; }
value_type &operator[](size_type pos) { return m_memory[pos]; }
const value_type &operator[](size_type pos) const { return m_memory[pos]; }
private:
pointer m_memory;
size_type m_size, m_capacity;
void alloc(size_type capacity) {
m_capacity = capacity;
m_size = 0;
m_memory =
static_cast<pointer>(detail::podvector::malloc<value_type>(capacity));
if (!m_memory)
throw std::bad_alloc{};
}
void change_capacity(size_type new_capacity) {
m_capacity = new_capacity;
void *new_memory =
detail::podvector::realloc<value_type>(m_memory, new_capacity);
if (!new_memory)
throw std::bad_alloc{};
m_memory = static_cast<pointer>(new_memory);
}
};
} // namespace gupta