1 static class Foo{
2 int i;
3
4 this(int i)pure nothrow @safe @nogc{
5 this.i = i;
6 }
7 }
8
9 static class Bar : Foo{
10 double d;
11
12 this(int i, double d)pure nothrow @safe @nogc{
13 super(i);
14 this.d = d;
15 }
16 }
17
18 static class Zee : Bar{
19 bool b;
20
21 this(int i, double d, bool b)pure nothrow @safe @nogc{
22 super(i, d);
23 this.b = b;
24 }
25
26 ~this()nothrow @system{
27 }
28 }
29
30 import core.lifetime : move;
31 ///simple:
32 {
33 UniquePtr!long a = UniquePtr!long.make(42);
34 UniquePtr!(const long) b = move(a);
35 assert(a == null);
36
37 assert(*b == 42);
38 assert(b.get == 42);
39 }
40
41 ///polymorphism:
42 {
43 ///create UniquePtr
44 UniquePtr!Foo foo = UniquePtr!Bar.make(42, 3.14);
45 UniquePtr!Zee zee = UniquePtr!Zee.make(42, 3.14, false);
46
47 ///dynamic cast:
48 UniquePtr!Bar bar = dynCastMove!Bar(foo);
49 assert(foo == null);
50 assert(bar != null);
51
52 ///this doesnt work because Foo destructor attributes are more restrictive then Zee's:
53 //UniquePtr!Foo x = move(zee);
54
55 ///this does work:
56 UniquePtr!(Foo, DestructorType!(Foo, Zee)) x = move(zee);
57 assert(zee == null);
58 }
59
60
61 ///multi threading:
62 {
63 ///create SharedPtr with atomic ref counting
64 UniquePtr!(shared Foo) foo = UniquePtr!(shared Bar).make(42, 3.14);
65
66 ///this doesnt work:
67 //foo.get.i += 1;
68
69 import core.atomic : atomicFetchAdd;
70 atomicFetchAdd(foo.get.i, 1);
71 assert(foo.get.i == 43);
72
73
74 ///creating `shared(UniquePtr)`:
75 shared UniquePtr!(shared Bar) bar = share(dynCastMove!Bar(foo));
76
77 ///`shared(UniquePtr)` is lock free.
78 static assert(typeof(bar).isLockFree == true);
79
80 ///multi thread operations (`store`, `exchange`):
81 UniquePtr!(shared Bar) bar2 = bar.exchange(null);
82 }
83
84 ///dynamic array:
85 {
86 import std.algorithm : all, equal;
87
88 UniquePtr!(long[]) a = UniquePtr!(long[]).make(10, -1);
89 assert(a.length == 10);
90 assert(a.get.length == 10);
91 assert(a.get.all!(x => x == -1));
92
93 for(int i = 0; i < a.length; ++i){
94 a.get[i] = i;
95 }
96 assert(a.get[] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
97 }//make UniquePtr object
static struct Foo{
int i;
this(int i)pure nothrow @safe @nogc{
this.i = i;
}
}
{
auto foo = UniquePtr!Foo.make(42);
auto foo2 = UniquePtr!Foo.make!Mallocator(42); //explicit stateless allocator
}
{
auto arr = UniquePtr!(long[]).make(10); //dynamic array with length 10
assert(arr.length == 10);
}//alloc UniquePtr object
import std.experimental.allocator : make, dispose, allocatorObject;
auto allocator = allocatorObject(Mallocator.instance);
{
auto x = UniquePtr!(long).alloc(allocator, 42);
}
{
auto arr = UniquePtr!(long[]).alloc(allocator, 10); //dynamic array with length 10
assert(arr.length == 10);
}{
auto x = UniquePtr!(shared long).make(123);
import core.lifetime : move;
shared s = share(x.move);
assert(x == null);
auto y = s.exchange(null);
assert(*y == 123);
}
{
auto x = UniquePtr!(long).make(123);
///error `shared UniquePtr` need shared `ControlType` and shared `ElementType`.
//shared s = share(x);
}
UniquePtr is a smart pointer that owns and manages object through a pointer and disposes of that object when the UniquePtr goes out of scope.
UniquePtr is alias to btl.autoptr.rc_ptr.RcPtr with immutable _ControlType.
The object is destroyed and its memory deallocated when either of the following happens:
1. the managing UniquePtr object is destroyed
2. the managing UniquePtr object is assigned another pointer via various methods like opAssign and store.
The object is destroyed using delete-expression or a custom deleter that is supplied to UniquePtr during construction.
A UniquePtr may alternatively own no object, in which case it is called empty.
Template parameters:
_Type type of managed object
_DestructorType function pointer with attributes of destructor, to get attributes of destructor from type use btl.autoptr.common.DestructorType!T. Destructor of type _Type must be compatible with _DestructorType
_ControlType represent type of counter, must by of type immutable btl.autoptr.common.ControlBlock.