Skip to content

Instantly share code, notes, and snippets.

@kerrytazi
Created January 21, 2026 11:07
Show Gist options
  • Select an option

  • Save kerrytazi/198d82056e1b7e2608145802f1264563 to your computer and use it in GitHub Desktop.

Select an option

Save kerrytazi/198d82056e1b7e2608145802f1264563 to your computer and use it in GitHub Desktop.
Implementation of vector with size of 64 bits
#include <cstddef>
#include <cstdint>
#include <bit>
#include <stdexcept>
#include <memory>
template <typename T>
struct micro_vector
{
using size_type = size_t;
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using move_reference = T&&;
micro_vector() = default;
micro_vector(const micro_vector& other)
{
_copy_from(other);
}
micro_vector& operator=(const micro_vector& other)
{
_destroy();
_copy_from(other);
return *this;
}
micro_vector(micro_vector&& other)
{
swap(other);
}
micro_vector& operator=(micro_vector&& other)
{
swap(other);
return *this;
}
~micro_vector()
{
_destroy();
}
size_type capacity() const
{
return 1 << 16;
}
size_type size() const
{
return _get_size();
}
pointer data()
{
return std::bit_cast<pointer>(_get_data());
}
const_pointer data() const
{
return std::bit_cast<const_pointer>(_get_data());
}
bool empty() const { return size() == 0; }
pointer begin() { return data(); }
pointer end() { return data() + size(); }
const const_pointer begin() const { return data(); }
const const_pointer end() const { return data() + size(); }
const const_pointer cbegin() const { return data(); }
const const_pointer cend() const { return data() + size(); }
template <typename... TArgs>
reference emplace_back(TArgs&&... args)
{
_alloc_inner();
auto s = size();
auto p = data();
if (s + 1 >= capacity())
throw std::bad_alloc();
std::construct_at(&p[s], std::forward<TArgs>(args)...);
_set_size(s + 1);
return p[s];
}
reference emplace_back(move_reference val)
{
_alloc_inner();
auto s = size();
auto p = data();
if (s + 1 >= capacity())
throw std::bad_alloc();
std::construct_at<value_type>(&p[s], std::move(val));
_set_size(s + 1);
return p[s];
}
void push_back(const_reference val)
{
emplace_back(val);
}
void push_back(move_reference val)
{
emplace_back(std::move(val));
}
void swap(micro_vector& other)
{
std::swap(_val, other._val);
}
void _copy_from(const micro_vector& other)
{
if (!other._val)
return;
for (const_reference val : other)
push_back(val);
}
void _alloc_inner()
{
if (data())
return;
_val = std::bit_cast<size_type>(std::allocator<value_type>{}.allocate(capacity()));
}
void _destroy()
{
if (_val == 0)
return;
for (auto it = begin(); it != end(); ++it)
std::destroy_at(it);
std::allocator<value_type>{}.deallocate(data(), capacity());
_val = 0;
}
size_type _get_size() const { return _val >> 48; }
size_type _get_data() const { return _val & 0x0000'ffff'ffff'ffff; }
void _set_size(size_type new_size)
{
_val = (new_size << 48) | _get_data();
}
size_type _val = 0;
};
static_assert(sizeof(void*) == 8, "Only 64 bit systems supported");
static_assert(sizeof(micro_vector<int>) == 8, "How?");
#include "micro_vector.hpp"
#include <iostream>
int main()
{
micro_vector<int> vec1;
vec1.push_back(123);
vec1.push_back(456);
vec1.push_back(789);
auto vec2 = vec1;
vec2.emplace_back(654);
std::cout << "vec1:\n";
for (auto val : vec1)
std::cout << val << "\n";
std::cout << "vec2:\n";
for (auto val : vec2)
std::cout << val << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment