競技プログラミング用 C++ ライブラリ
components/aligned_allocator.hpp · GitHub で見る
共通ページ
std::vector などに指定できる、境界を指定したアロケータです。
#include "lib/components/aligned_allocator.hpp"
#include <cstdint>
#include <vector>
std::vector<std::int64_t, AlignedAllocator<std::int64_t>> values(100);
AlignedAllocator<T,Alignment=64> は、確保する先頭アドレスを Alignment byte の倍数に揃えます。Alignment は alignof(T) 以上の 2 の冪です。allocate(n) は n 要素の未初期化領域を返し、deallocate(p,n) は同じアロケータで確保した領域を解放します。同じ Alignment のアロケータは互換です。
確保できない場合は std::bad_alloc、要素数からバイト数への変換がオーバーフローする場合は std::bad_array_new_length を送出します。
確保する空間は \(O(n)\) です。確保と解放の時間は OS とアロケータに依存します。
#ifndef ALIGNED_ALLOCATOR_HPP
#define ALIGNED_ALLOCATOR_HPP
#include <cstddef>
#include <limits>
#include <new>
template<class T, std::size_t Alignment = 64> struct AlignedAllocator {
static_assert(Alignment >= alignof(T) && !(Alignment & (Alignment - 1)));
using value_type = T;
template<class U> struct rebind { using other = AlignedAllocator<U, Alignment>; };
AlignedAllocator() = default;
template<class U> AlignedAllocator(const AlignedAllocator<U, Alignment> &) {}
T *allocate(std::size_t n) {
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T)) throw std::bad_array_new_length();
return static_cast<T *>(::operator new(n * sizeof(T), std::align_val_t(Alignment)));
}
void deallocate(T *p, std::size_t) { ::operator delete(p, std::align_val_t(Alignment)); }
template<class U> bool operator==(const AlignedAllocator<U, Alignment> &) const { return true; }
};
#endif
#line 1 "components/aligned_allocator.hpp"
#include <cstddef>
#include <limits>
#include <new>
template<class T, std::size_t Alignment = 64> struct AlignedAllocator {
static_assert(Alignment >= alignof(T) && !(Alignment & (Alignment - 1)));
using value_type = T;
template<class U> struct rebind { using other = AlignedAllocator<U, Alignment>; };
AlignedAllocator() = default;
template<class U> AlignedAllocator(const AlignedAllocator<U, Alignment> &) {}
T *allocate(std::size_t n) {
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T)) throw std::bad_array_new_length();
return static_cast<T *>(::operator new(n * sizeof(T), std::align_val_t(Alignment)));
}
void deallocate(T *p, std::size_t) { ::operator delete(p, std::align_val_t(Alignment)); }
template<class U> bool operator==(const AlignedAllocator<U, Alignment> &) const { return true; }
};