emplace 0.3.1
GC-free, allocator-aware containers and smart pointers for D — C++/Rust-grade, so non-GC D no longer means C-isms. Vector, Map/OrderedSet (red-black), Uniq/Shared/Weak.
To use this package, run the following command in your project's root directory:
Manual usage
Put the following dependency into your project's dependences section:
emplace
C++-grade, GC-free data structures and smart pointers for D.
Writing @nogc D today usually means falling back to C-isms — raw pointers,
manual malloc/free, hand-rolled containers. emplace closes that gap: the
containers and smart pointers you expect from C++'s <memory>/<vector>/<map>,
allocator-aware (Alexandrescu's std.experimental.allocator), @nogc when the
allocator is, and correct on current LDC/DMD.
Install
dub add emplace
import emplace.smartptr : Uniq, Shared, Weak;
import emplace.vector : Vector;
import emplace.map : Map, OrderedSet;
What's in the box
Smart pointers (emplace.smartptr) — modeled on libc++'s <memory>
- `Uniq!(T, Alloc = Mallocator)` —
unique_ptr: single ownership, move-only, plus Rust-flavoredborrow/take(Option::take) /intoInner(Box::into_inner). - `Shared!(T, Alloc = Mallocator)` —
shared_ptr: reference counted, copy bumps the count,make_shared-style inline control block (one allocation), with a weak count. - `Weak!(T, Alloc = Mallocator)` —
weak_ptr: non-owning observer,lock()/expired.
Containers
- `emplace.vector.Vector!(T, Alloc = Mallocator)` — a dynamic array; bulk
put(slice)is a singlememcpy(not a per-element loop).shrinkToFit(shrink_to_fit). `Vector!bool` is bit-packed (std::vector<bool>): one bit per element,opIndexreturns an assignable proxy bit-reference. - `emplace.deque.Deque!(T, Alloc = Mallocator)` — a double-ended queue: a circular buffer over one contiguous block, O(1) push/pop at both ends and O(1) random access. Releases memory as it drains (halves capacity at ¼ load, frees at empty) — safe for long-running FIFOs.
- `emplace.map.Map!(K, V)` — an ordered map on a hand-rolled red-black tree
(O(log n) insert/lookup/remove, sorted iteration,
leftBound/rightBoundfloor/ceiling +foreachRange,removeRightconsuming prefix range). - `emplace.map.OrderedSet!T` — the ordered set: the valueless companion (union / intersection / difference / symmetric difference, subset / superset).
- `emplace.hashmap.HashMap!(K, V)` —
unordered_map: open-addressed hash table, linear probing with backward-shift deletion (no tombstones). - `emplace.hashmap.HashSet!K` —
unordered_set.
Every container is RAII and smart-pointer safe: elements are moved into
place, and popBack/clear/~this release each one (its .free() or
destructor), so a Vector!(Uniq!T) or Deque!(Shared!T) never leaks. Each is
copyable exactly when its element is (a deep, independent copy — Map deep-
clones its tree like std::map); an element with a move-only type (e.g. Uniq)
makes the whole container move-only, so a bitwise copy can never double-free.
All expose D ranges (opSlice).
Allocators
Everything is parameterized on an std.experimental.allocator allocator,
defaulting to Mallocator. Attributes are inferred, so with Mallocator
the whole surface is @nogc nothrow; plug GCAllocator, FreeList, Region,
InSituRegion, or your own — unchanged.
import std.experimental.allocator.building_blocks.free_list : FreeList;
import std.experimental.allocator.mallocator : Mallocator;
// a node pool: ~10-16x cheaper per allocation than malloc in our benchmarks
alias Pool = FreeList!(Mallocator, 64);
Example
import emplace.smartptr : Uniq, Shared;
import emplace.vector : Vector;
@nogc nothrow:
auto box = Uniq!int.make(42); // owns a heap int, freed on scope exit
int taken = box.intoInner(); // move the value out (Box::into_inner)
auto rc = Shared!string.make("hi");
auto rc2 = rc; // refcount == 2, freed when the last dies
Vector!ubyte buf;
buf.put(cast(const(ubyte)[]) "hello"); // one memcpy, no per-byte loop
Acknowledgements
emplace was originally built for [dreads](https://github.com/caetanus/dreads),
a GC-free Redis/Valkey-compatible database in D, whose data plane runs with the
collector disabled — so it needed exactly these containers without C-isms. It is
extracted here as a standalone, reusable package.
It is inspired by [automem](https://github.com/atilaneves/automem) by
Atila Neves, which pioneered allocator-aware smart pointers and a vector for
D. emplace carries that idea forward with a wider container set, libc++/Rust
semantics, and fixes for issues that surface on current compilers. Credit for the
original direction is his.
License
MIT — see LICENSE. Copyright © 2026 Marcelo Aires Caetano.
- 0.3.1 released 18 days ago
- caetanus/emplace
- MIT
- Authors:
- Dependencies:
- none
- Versions:
-
Show all 7 versions0.4.0 2026-Jul-21 0.3.1 2026-Jul-18 0.3.0 2026-Jul-15 0.2.0 2026-Jul-14 0.1.0 2026-Jul-11 - Download Stats:
-
-
0 downloads today
-
0 downloads this week
-
0 downloads this month
-
0 downloads total
-
- Score:
- 0.1
- Short URL:
- emplace.dub.pm