1 /** Extra traits for `std.experimental.allocator`; 2 */ 3 module nxt.allocator_traits; 4 5 /** Is `true` iff `T` is an allocator, otherwise `false`. 6 * 7 * Only members and `alignment` and `allocate` are required. 8 * 9 * See_Also: https://dlang.org/phobos/std_experimental_allocator_building_blocks.html 10 * See_Also: https://forum.dlang.org/post/uiavxptceyxsjulkxlec@forum.dlang.org 11 */ 12 enum isAllocator(T) = (is(typeof(T.allocate(size_t.init)) == void[]) 13 && is(typeof(T.alignment) : size_t) // currently either uint or size_t 14 // && __traits(compiles, { enum uint _ = T.alignment; }) 15 ); 16 17 version(unittest) 18 { 19 import std.experimental.allocator.building_blocks.null_allocator : NullAllocator; 20 import std.experimental.allocator.mallocator : Mallocator; 21 import std.experimental.allocator.gc_allocator : GCAllocator; 22 import std.experimental.allocator.mmap_allocator : MmapAllocator; 23 } 24 25 version(unittest) 26 { 27 static assert(isAllocator!NullAllocator); 28 static assert(isAllocator!Mallocator); 29 static assert(isAllocator!GCAllocator); 30 static assert(isAllocator!MmapAllocator); 31 static assert(!isAllocator!int); 32 } 33 34 /** State of allocator. 35 * 36 * State is zero for `Mallocator`, `GCAllocator`, and `MMapAllocator` and 37 * typically non-zero for the other. 38 * 39 * EMSI containers has this state as their first field. 40 * 41 * TODO: Move to Phobos and put beside 42 * std.experimental.allocator.common.stateSize. 43 */ 44 mixin template AllocatorState(Allocator) // TODO: add string fieldName parameter 45 if (isAllocator!Allocator) 46 { 47 private import std.experimental.allocator.common : stateSize; 48 static if (stateSize!Allocator == 0) 49 alias allocator = Allocator.instance; 50 else 51 Allocator allocator; 52 } 53 54 version(unittest) 55 { 56 mixin AllocatorState!GCAllocator g; 57 mixin AllocatorState!Mallocator m; 58 mixin AllocatorState!MmapAllocator p; 59 } 60 61 version(none): 62 63 /** Is `true` iff `T` is an allocator, otherwise `false`. 64 */ 65 template isAllocator1(T) 66 { 67 import std.experimental.allocator : IAllocator, CAllocatorImpl; 68 enum isAllocator1 = __traits(compiles, { IAllocator alloc = new CAllocatorImpl!T; }); 69 } 70 71 version(unittest) 72 { 73 import std.experimental.allocator.mallocator : Mallocator; 74 static assert(isAllocator1!Mallocator); 75 static assert(!isAllocator1!int); 76 } 77 78 bool isAllocator2(T)() pure { 79 import std.experimental.allocator : CAllocatorImpl; 80 return __traits(compiles, { new CAllocatorImpl!T; }); 81 } 82 83 version(unittest) 84 { 85 import std.experimental.allocator.mallocator : Mallocator; 86 static assert(isAllocator2!Mallocator); 87 static assert(!isAllocator2!int); 88 }