1 module automem.traits; 2 3 4 void checkAllocator(T)() { 5 import std.experimental.allocator: make, dispose; 6 import std.traits: hasMember; 7 8 static if(hasMember!(T, "instance")) 9 alias allocator = T.instance; 10 else 11 T allocator; 12 13 int* i = allocator.make!int; 14 allocator.dispose(&i); 15 void[] bytes = allocator.allocate(size_t.init); 16 allocator.deallocate(bytes); 17 } 18 19 enum isAllocator(T) = is(typeof(checkAllocator!T)); 20 21 22 @("isAllocator") 23 @safe @nogc pure unittest { 24 import std.experimental.allocator.mallocator: Mallocator; 25 import test_allocator: TestAllocator; 26 27 static assert( isAllocator!Mallocator); 28 static assert( isAllocator!TestAllocator); 29 static assert(!isAllocator!int); 30 } 31 32 33 template isGlobal(Allocator) { 34 enum isGlobal = isSingleton!Allocator || isTheAllocator!Allocator; 35 } 36 37 template isSingleton(Allocator) { 38 import std.traits: hasMember; 39 enum isSingleton = hasMember!(Allocator, "instance"); 40 } 41 42 template isTheAllocator(Allocator) { 43 import std.experimental.allocator: theAllocator; 44 enum isTheAllocator = is(Allocator == typeof(theAllocator)); 45 } 46 47 /** 48 Determines if a type is Unique. 49 */ 50 template isUnique(T) { 51 import automem.unique: Unique; 52 import std.traits: TemplateOf; 53 enum isUnique = __traits(isSame, TemplateOf!T, Unique); 54 } 55 56 /// 57 @("isUnique") 58 @safe unittest { 59 import automem.unique: Unique; 60 61 static struct Point { 62 int x; 63 int y; 64 } 65 66 auto u = Unique!Point(2, 3); 67 static assert(isUnique!(typeof(u))); 68 69 auto p = Point(2, 3); 70 static assert(!isUnique!(typeof(p))); 71 } 72 73 /** 74 Determines if a type is RefCounted. 75 */ 76 template isRefCounted(T) { 77 import automem.ref_counted: RefCounted; 78 import std.traits: TemplateOf; 79 enum isRefCounted = __traits(isSame, TemplateOf!T, RefCounted); 80 } 81 82 /// 83 @("isRefCounted") 84 @safe unittest { 85 import automem.ref_counted: RefCounted; 86 87 static struct Point { 88 int x; 89 int y; 90 } 91 92 auto s = RefCounted!Point(2, 3); 93 static assert(isRefCounted!(typeof(s))); 94 95 auto p = Point(2, 3); 96 static assert(!isRefCounted!(typeof(p))); 97 } 98 99 100 /** 101 The target of a `Unique` or `RefCounted` pointer. 102 */ 103 template PointerTarget(T) 104 if (isUnique!T || isRefCounted!T) 105 { 106 alias PointerTarget = T.Type; 107 } 108 109 /// 110 @("Get the target of a Unique or RefCounter pointer") 111 @safe unittest { 112 import automem.unique: Unique; 113 import automem.ref_counted: RefCounted; 114 115 static struct Point { 116 int x; 117 int y; 118 } 119 120 auto u = Unique!Point(2, 3); 121 static assert(is(Point == PointerTarget!(typeof(u)))); 122 123 auto s = RefCounted!Point(2, 3); 124 static assert(is(Point == PointerTarget!(typeof(s)))); 125 } 126 127 /// 128 @("Mixing Unique and RefCounted pointers") 129 unittest { 130 import std.math : approxEqual; 131 import automem.unique: Unique; 132 import automem.ref_counted: RefCounted; 133 134 static struct Point { 135 int x; 136 int y; 137 } 138 139 static double distance(T, U)(auto ref T p1, auto ref U p2) 140 if (is(PointerTarget!T == Point) && 141 is(PointerTarget!U == Point)) 142 { 143 import std.conv : to; 144 import std.math : sqrt, pow; 145 return((pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2)).to!double.sqrt); 146 } 147 148 int x1 = 2; 149 int y1 = 3; 150 int x2 = x1 + 3; 151 int y2 = y1 + 4; 152 153 auto u_p1 = Unique!Point(x1, y1); 154 auto u_p2 = Unique!Point(x2, y2); 155 assert(approxEqual(distance(u_p1, u_p2), 5.0)); 156 157 auto rc_p1 = RefCounted!Point(x1, y1); 158 auto rc_p2 = RefCounted!Point(x2, y2); 159 assert(approxEqual(distance(rc_p1, rc_p2), 5.0)); 160 161 assert(approxEqual(distance(u_p1, rc_p2), 5.0)); 162 assert(approxEqual(distance(rc_p1, u_p2), 5.0)); 163 }