template <std::size_t N>
char*
arena<N>::allocate(std::size_t n)
{
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
n = align_up(n);
if (buf_ + N - ptr_ >= n)
{
char* r = ptr_;
ptr_ += n;
return r;
}
return static_cast<char*>(::operator new(n));
}
、一つは単に適切alignment
を微調整することができます。そして、もう一つは、また、これはあなたが下向きalignment
を調整した場合、あなたはあまりにも遠く下向きに調整していないという確信を与えるだろうalignof(T)
template <std::size_t N>
char*
arena<N>::allocate(std::size_t n, std::size_t requested_align)
{
assert(requested_align <= alignment);
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
n = align_up(n);
if (buf_ + N - ptr_ >= n)
{
char* r = ptr_;
ptr_ += n;
return r;
}
return static_cast<char*>(::operator new(n));
}
arena::allocate
にとassert(requested_align <= alignment)
short_alloc::allocate
パスを持つことができます。
もう一度アップデートしてください!
私はこの優れた質問のためにこのアロケータのdescriptionとcodeをかなり更新しました(私はこのコードを長年無視していました)。
以前のアップデートで言及されたアライメントチェックはコンパイル時に行われました(コンパイル時エラーは常にランタイムエラーよりも優れており、アサートさえも優れています)。
arena
とshort_alloc
は、現在、整列時にテンプレート化されているため、予想通りの整列要件を簡単にカスタマイズできます(あまりにも小さいと推測すると、コンパイル時に検出されます)。このテンプレートパラメータのデフォルトはalignof(std::max_align_t)
です。
arena::allocate
機能は今のようになります。
template <std::size_t N, std::size_t alignment>
template <std::size_t ReqAlign>
char*
arena<N, alignment>::allocate(std::size_t n)
{
static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
auto const aligned_n = align_up(n);
if (buf_ + N - ptr_ >= aligned_n)
{
char* r = ptr_;
ptr_ += aligned_n;
return r;
}
return static_cast<char*>(::operator new(n));
}
エイリアステンプレートのおかげで、このアロケータは、これまで以上に使いやすくなります。例えば:
// Create a vector<T> template with a small buffer of 200 bytes.
// Note for vector it is possible to reduce the alignment requirements
// down to alignof(T) because vector doesn't allocate anything but T's.
// And if we're wrong about that guess, it is a comple-time error, not
// a run time error.
template <class T, std::size_t BufSize = 200>
using SmallVector = std::vector<T, short_alloc<T, BufSize, alignof(T)>>;
// Create the stack-based arena from which to allocate
SmallVector<int>::allocator_type::arena_type a;
// Create the vector which uses that arena.
SmallVector<int> v{a};
これは必ずしもそのようなアロケータの最後の単語ではありません。しかし、うまくいけば、これはあなたのカスタムアロケータを構築するための強固な基盤です。
ページングドクター[@HowardHinnant](http://stackoverflow.com/users/576911/howard-hinnant) – sehe