UniquePtr

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.

  1. template UniquePtr(_Type, _DestructorType = DestructorType!_Type, _ControlType = immutable(UniqueControlBlock))
  2. template UniquePtr(_Type, _ControlType, _DestructorType = DestructorType!_Type)
    template UniquePtr (
    _Type
    _ControlType
    _DestructorType = DestructorType!_Type
    ) if (
    isControlBlock!_ControlType &&
    isDestructorType!_DestructorType
    ) {}

Members

Aliases

UniquePtr
alias UniquePtr = btl.autoptr.rc_ptr.RcPtr!(_Type, _DestructorType, _ControlType)
Undocumented in source.

Examples

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);

}

Meta