summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2019-02-15 08:36:42 +0100
committerEugen Wissner <belka@caraus.de>2019-02-16 08:36:50 +0100
commit0835edce1d3c8bd2b09baa2b76d38efd3848027e (patch)
treef63d26aea45ea4e63a8e3e53b699da87a4414b71 /source
parenta786bdbec5575bcfad6435978755064e1be5e975 (diff)
downloadtanya-0835edce1d3c8bd2b09baa2b76d38efd3848027e.tar.gz
range.adapter: Add container-range adapters. Fix #67
Diffstat (limited to 'source')
-rw-r--r--source/tanya/range/adapter.d114
1 files changed, 105 insertions, 9 deletions
diff --git a/source/tanya/range/adapter.d b/source/tanya/range/adapter.d
index 7c3cb5e..5dfcf5b 100644
--- a/source/tanya/range/adapter.d
+++ b/source/tanya/range/adapter.d
@@ -28,24 +28,67 @@ version (unittest)
}
}
-package (tanya) auto backInserter(Container)(return ref Container container)
-if (hasMember!(Container, "insertBack"))
+private mixin template InserterCtor()
{
- static struct BackInserter
+ private Container* container;
+
+ this(ref Container container) @trusted
{
- private Container* container;
+ this.container = &container;
+ }
+}
- this(ref Container container) @trusted
+/**
+ * If $(D_PARAM container) is a container with `insertBack`-support,
+ * $(D_PSYMBOL backInserter) returns an output range that puts the elements
+ * into the container with `insertBack`.
+ *
+ * The resulting output range supports all types `insertBack` supports.
+ *
+ * The range keeps a reference to the container passed to it, it doesn't use
+ * any other storage. So there is no method to get the written data out of the
+ * range - the container passed to $(D_PSYMBOL backInserter) contains that data
+ * and can be used directly after all operations on the output range are
+ * completed. It also means that the result range is not allowed to outlive its
+ * container.
+ *
+ * Params:
+ * Container = Container type.
+ * container = Container used as an output range.
+ *
+ * Returns: `insertBack`-based output range.
+ */
+auto backInserter(Container)(return scope ref Container container)
+if (hasMember!(Container, "insertBack"))
+{
+ static struct Inserter
+ {
+ void opCall(T)(auto ref T data)
{
- this.container = &container;
+ this.container.insertBack(forward!data);
}
- void opCall(T)(auto ref T data)
+ mixin InserterCtor;
+ }
+ return Inserter(container);
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ static struct Container
+ {
+ int element;
+
+ void insertBack(int element)
{
- this.container.insertBack(forward!data);
+ this.element = element;
}
}
- return BackInserter(container);
+ Container container;
+ backInserter(container)(5);
+
+ assert(container.element == 5);
}
@nogc nothrow pure @safe unittest
@@ -63,3 +106,56 @@ if (hasMember!(Container, "insertBack"))
Container container;
static assert(isOutputRange!(typeof(backInserter(container)), string));
}
+
+/**
+ * If $(D_PARAM container) is a container with `insertFront`-support,
+ * $(D_PSYMBOL frontInserter) returns an output range that puts the elements
+ * into the container with `insertFront`.
+ *
+ * The resulting output range supports all types `insertFront` supports.
+ *
+ * The range keeps a reference to the container passed to it, it doesn't use
+ * any other storage. So there is no method to get the written data out of the
+ * range - the container passed to $(D_PSYMBOL frontInserter) contains that data
+ * and can be used directly after all operations on the output range are
+ * completed. It also means that the result range is not allowed to outlive its
+ * container.
+ *
+ * Params:
+ * Container = Container type.
+ * container = Container used as an output range.
+ *
+ * Returns: `insertFront`-based output range.
+ */
+auto frontInserter(Container)(return scope ref Container container)
+if (hasMember!(Container, "insertFront"))
+{
+ static struct Inserter
+ {
+ void opCall(T)(auto ref T data)
+ {
+ this.container.insertFront(forward!data);
+ }
+
+ mixin InserterCtor;
+ }
+ return Inserter(container);
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ static struct Container
+ {
+ int element;
+
+ void insertFront(int element)
+ {
+ this.element = element;
+ }
+ }
+ Container container;
+ frontInserter(container)(5);
+
+ assert(container.element == 5);
+}