summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-05-30 20:20:20 +0200
committerEugen Wissner <belka@caraus.de>2017-05-30 20:20:20 +0200
commit0f365758e11ca1669e31324bc6f530186d7c950a (patch)
tree14402bdaece48c4bcbf483554e68459a6ad9d46f
parent2815b53a88330534de4756db11960aee72fd7da2 (diff)
downloadtanya-0f365758e11ca1669e31324bc6f530186d7c950a.tar.gz
Add optional fieldnames for Pair
-rw-r--r--source/tanya/typecons.d78
1 files changed, 72 insertions, 6 deletions
diff --git a/source/tanya/typecons.d b/source/tanya/typecons.d
index cf09d52..62e9df4 100644
--- a/source/tanya/typecons.d
+++ b/source/tanya/typecons.d
@@ -5,6 +5,9 @@
/**
* Type constructors.
*
+ * This module contains templates that allow to build new types from the
+ * available ones.
+ *
* Copyright: Eugene Wissner 2017.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
@@ -15,17 +18,70 @@ module tanya.typecons;
import std.meta;
/**
- * $(D_PSYMBOL Pair) can store two heterogeneous objects. The objects can be
- * accessed than by the index. The objects can by accessed by index as
- * $(D_INLINECODE obj[0]) and $(D_INLINECODE obj[1]).
+ * $(D_PSYMBOL Pair) can store two heterogeneous objects.
+ *
+ * The objects can by accessed by index as $(D_INLINECODE obj[0]) and
+ * $(D_INLINECODE obj[1]) or by optional names (e.g.
+ * $(D_INLINECODE obj.first)).
+ *
+ * $(D_PARAM Specs) contains a list of object types and names. First
+ * comes the object type, then an optional string containing the name.
+ * If you want the object be accessible only by its index (`0` or `1`),
+ * just skip the name.
+ *
+ * Params:
+ * Specs = Field types and names.
*/
-template Pair(Field1, Field2)
+template Pair(Specs...)
{
- /// Field types.
- alias Types = AliasSeq!(Field1, Field2);
+ template parseSpecs(int fieldCount, Specs...)
+ {
+ static if (Specs.length == 0)
+ {
+ alias parseSpecs = AliasSeq!();
+ }
+ else static if (is(Specs[0]) && fieldCount < 2)
+ {
+ static if (is(typeof(Specs[1]) == string))
+ {
+ alias parseSpecs
+ = AliasSeq!(Specs[0],
+ parseSpecs!(fieldCount + 1, Specs[2 .. $]));
+ }
+ else
+ {
+ alias parseSpecs
+ = AliasSeq!(Specs[0],
+ parseSpecs!(fieldCount + 1, Specs[1 .. $]));
+ }
+ }
+ else
+ {
+ static assert(false, "Invalid argument: " ~ Specs[0].stringof);
+ }
+ }
struct Pair
{
+ /// Field types.
+ alias Types = parseSpecs!(0, Specs);
+
+ static assert(Types.length == 2, "Invalid argument count.");
+
+ // Create field aliases.
+ static if (is(typeof(Specs[1]) == string))
+ {
+ mixin("alias " ~ Specs[1] ~ " = expand[0];");
+ }
+ static if (is(typeof(Specs[2]) == string))
+ {
+ mixin("alias " ~ Specs[2] ~ " = expand[1];");
+ }
+ else static if (is(typeof(Specs[3]) == string))
+ {
+ mixin("alias " ~ Specs[3] ~ " = expand[1];");
+ }
+
/// Represents the values of the $(D_PSYMBOL Pair) as a list of values.
Types expand;
@@ -38,4 +94,14 @@ unittest
{
static assert(is(Pair!(int, int)));
static assert(!is(Pair!(int, 5)));
+
+ static assert(is(Pair!(int, "first", int)));
+ static assert(is(Pair!(int, "first", int, "second")));
+ static assert(is(Pair!(int, "first", int)));
+
+ static assert(is(Pair!(int, int, "second")));
+ static assert(!is(Pair!("first", int, "second", int)));
+ static assert(!is(Pair!(int, int, int)));
+
+ static assert(!is(Pair!(int, "first")));
}