Alias 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.

alias UniquePtr(_Type, _DestructorType, _ControlType) = RcPtr!(_Type,_DestructorType,_ControlType);
alias UniquePtr(_Type, _ControlType, _DestructorType) = RcPtr!(_Type,_DestructorType,_ControlType);

UniquePtr is alias to 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 DestructorType!T. Destructor of type _Type must be compatible with _DestructorType

_ControlType represent type of counter, must by of type immutable ControlBlock.

Example

static class Foo{
    int i;

    this(int i)pure nothrow @safe @nogc{
        this.i = i;
    }
}

static class Bar : Foo{
    double d;

    this(int i, double d)pure nothrow @safe @nogc{
        super(i);
        this.d = d;
    }
}

static class Zee : Bar{
    bool b;

    this(int i, double d, bool b)pure nothrow @safe @nogc{
        super(i, d);
        this.b = b;
    }

    ~this()nothrow @system{
    }
}

import core.lifetime : move;
///simple:
{
    UniquePtr!long a = UniquePtr!long.make(42);
    UniquePtr!(const long) b = move(a);
    assert(a == null);

    assert(*b == 42);
    assert(b.get == 42);
}

///polymorphism:
{
    ///create UniquePtr
    UniquePtr!Foo foo = UniquePtr!Bar.make(42, 3.14);
    UniquePtr!Zee zee = UniquePtr!Zee.make(42, 3.14, false);

    ///dynamic cast:
    UniquePtr!Bar bar = dynCastMove!Bar(foo);
    assert(foo == null);
    assert(bar != null);

    ///this doesnt work because Foo destructor attributes are more restrictive then Zee's:
    //UniquePtr!Foo x = move(zee);

    ///this does work:
    UniquePtr!(Foo, DestructorType!(Foo, Zee)) x = move(zee);
    assert(zee == null);
}


///multi threading:
{
    ///create SharedPtr with atomic ref counting
    UniquePtr!(shared Foo) foo = UniquePtr!(shared Bar).make(42, 3.14);

    ///this doesnt work:
    //foo.get.i += 1;

    import core.atomic : atomicFetchAdd;
    atomicFetchAdd(foo.get.i, 1);
    assert(foo.get.i == 43);


    ///creating `shared(UniquePtr)`:
    shared UniquePtr!(shared Bar) bar = share(dynCastMove!Bar(foo));

    ///`shared(UniquePtr)` is lock free.
    static assert(typeof(bar).isLockFree == true);

    ///multi thread operations (`store`, `exchange`):
    UniquePtr!(shared Bar) bar2 = bar.exchange(null);
}

///dynamic array:
{
    import std.algorithm : all, equal;

    UniquePtr!(long[]) a = UniquePtr!(long[]).make(10, -1);
    assert(a.length == 10);
    assert(a.get.length == 10);
    assert(a.get.all!(x => x == -1));

    for(int i = 0; i < a.length; ++i){
        a.get[i] = i;
    }
    assert(a.get[] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
}

Example

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

Example

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

Example

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

}