From 9ea653eed4db0098402978453fcf2cfc382caac8 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Sun, 4 Sep 2016 22:24:57 -0600 Subject: [PATCH 1/4] Allow using Unique with interfaces --- std/typecons.d | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/std/typecons.d b/std/typecons.d index 62cf0fb6b8f..96ef731104a 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -56,7 +56,7 @@ class object, in which case Unique behaves polymorphically too. struct Unique(T) { /** Represents a reference to $(D T). Resolves to $(D T*) if $(D T) is a value type. */ -static if (is(T:Object)) +static if (is(T == class) || is(T == interface)) alias RefT = T; else alias RefT = T*; @@ -261,6 +261,35 @@ private: assert(!ub2.isEmpty); } +@system unittest +{ + debug(Unique) writeln("Unique interface"); + interface Bar + { + int val() const; + } + class BarImpl : Bar + { + ~this() { debug(Unique) writeln(" C destructor"); } + int val() const { return 4; }; + } + alias UBar = Unique!Bar; + UBar g(UBar u) + { + debug(Unique) writeln("inside g"); + return u.release; + } + auto ub = UBar(new BarImpl); + assert(!ub.isEmpty); + assert(ub.val == 4); + static assert(!__traits(compiles, {auto ub3 = g(ub);})); + debug(Unique) writeln("Calling g"); + auto ub2 = g(ub.release); + debug(Unique) writeln("Returned from g"); + assert(ub.isEmpty); + assert(!ub2.isEmpty); +} + @system unittest { debug(Unique) writeln("Unique struct"); From b6c2e381e9d3ee67c3bbf73d0d3740018e384677 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Mon, 5 Sep 2016 19:24:21 -0600 Subject: [PATCH 2/4] Add a little documentation --- std/typecons.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/typecons.d b/std/typecons.d index 96ef731104a..262e44ff169 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -51,7 +51,7 @@ Encapsulates unique ownership of a resource. Resource of type $(D T) is deleted at the end of the scope, unless it is transferred. The transfer can be explicit, by calling $(D release), or implicit, when returning Unique from a function. The resource can be a polymorphic -class object, in which case Unique behaves polymorphically too. +class object or instance of an interface, in which case Unique behaves polymorphically too. */ struct Unique(T) { From 7cbea7473ad16e52e7d5973793aa0dea5a9b9da4 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Thu, 16 Mar 2017 21:40:55 -0600 Subject: [PATCH 3/4] Remove trailing space --- std/typecons.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/typecons.d b/std/typecons.d index 6af4a3dc6a7..879a635f46e 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -61,7 +61,7 @@ $(D T) to deallocate or clean up any non-GC resources. If it is desirable to persist a $(D Unique!T) outside of its original scope, then it can be transferred. The transfer can be explicit, by calling $(D release), or implicit, when returning Unique from a -function. The resource $(D T) can be a polymorphic class object or +function. The resource $(D T) can be a polymorphic class object or instance of an interface, in which case Unique behaves polymorphically too. From 70a9e2a5030a85a8001c534f06952c9e777da053 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Thu, 16 Mar 2017 22:13:02 -0600 Subject: [PATCH 4/4] Improve unit test for Unique with interface --- std/typecons.d | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/std/typecons.d b/std/typecons.d index 879a635f46e..2b44c751b6e 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -290,7 +290,15 @@ private: } class BarImpl : Bar { - ~this() { debug(Unique) writeln(" C destructor"); } + static int count; + this() + { + count++; + } + ~this() + { + count--; + } int val() const { return 4; }; } alias UBar = Unique!Bar; @@ -299,7 +307,13 @@ private: debug(Unique) writeln("inside g"); return u.release; } + void consume(UBar u) + { + assert(u.val() == 4); + // Resource automatically deleted here + } auto ub = UBar(new BarImpl); + assert(BarImpl.count == 1); assert(!ub.isEmpty); assert(ub.val == 4); static assert(!__traits(compiles, {auto ub3 = g(ub);})); @@ -308,6 +322,8 @@ private: debug(Unique) writeln("Returned from g"); assert(ub.isEmpty); assert(!ub2.isEmpty); + consume(ub2.release); + assert(BarImpl.count == 0); } @system unittest