summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/tanya/meta/metafunction.d208
-rw-r--r--source/tanya/meta/trait.d151
-rw-r--r--source/tanya/meta/transform.d150
3 files changed, 337 insertions, 172 deletions
diff --git a/source/tanya/meta/metafunction.d b/source/tanya/meta/metafunction.d
index a683589..b619db0 100644
--- a/source/tanya/meta/metafunction.d
+++ b/source/tanya/meta/metafunction.d
@@ -112,7 +112,7 @@ pure nothrow @safe @nogc unittest
}
/**
- * Zips one or more $(D_PSYMBOL AliasTuple)s with $(D_PARAM f).
+ * Zips one or more $(D_PSYMBOL Tuple)s with $(D_PARAM f).
*
* Given $(D_PARAM f) and tuples t1, t2, ..., tk, where tk[i] denotes the
* $(I i)-th element of the tuple $(I k)-th tuple, $(D_PSYMBOL ZipWith)
@@ -137,7 +137,7 @@ pure nothrow @safe @nogc unittest
* Params:
* f = Some template that can be applied to the elements of
* $(D_PARAM Tuples).
- * Tuples = $(D_PSYMBOL AliasTuple) instances.
+ * Tuples = $(D_PSYMBOL Tuple) instances.
*
* Returns: A sequence, whose $(I i)-th element contains the $(I i)-th element
* from each of the $(D_PARAM Tuples).
@@ -145,7 +145,7 @@ pure nothrow @safe @nogc unittest
template ZipWith(alias f, Tuples...)
if (Tuples.length > 0
&& isTemplate!f
- && allSatisfy!(ApplyLeft!(isInstanceOf, AliasTuple), Tuples))
+ && allSatisfy!(ApplyLeft!(isInstanceOf, Tuple), Tuples))
{
private template GetIth(size_t i, Args...)
{
@@ -179,24 +179,24 @@ if (Tuples.length > 0
pure nothrow @safe @nogc unittest
{
alias Result1 = ZipWith!(AliasSeq,
- AliasTuple!(1, 2),
- AliasTuple!(5, 6),
- AliasTuple!(9, 10));
+ Tuple!(1, 2),
+ Tuple!(5, 6),
+ Tuple!(9, 10));
static assert(Result1 == AliasSeq!(1, 5, 9, 2, 6, 10));
alias Result2 = ZipWith!(AliasSeq,
- AliasTuple!(1, 2, 3),
- AliasTuple!(4, 5));
+ Tuple!(1, 2, 3),
+ Tuple!(4, 5));
static assert(Result2 == AliasSeq!(1, 4, 2, 5));
- alias Result3 = ZipWith!(AliasSeq, AliasTuple!(), AliasTuple!(4, 5));
+ alias Result3 = ZipWith!(AliasSeq, Tuple!(), Tuple!(4, 5));
static assert(Result3.length == 0);
}
/**
* Holds a typed sequence of template parameters.
*
- * Different than $(D_PSYMBOL AliasSeq), $(D_PSYMBOL AliasTuple) doesn't unpack
+ * Different than $(D_PSYMBOL AliasSeq), $(D_PSYMBOL Tuple) doesn't unpack
* its template parameters automatically. Consider:
*
* ---
@@ -211,7 +211,7 @@ pure nothrow @safe @nogc unittest
* Using $(D_PSYMBOL AliasSeq) template `A` gets 4 parameters instead of 2,
* because $(D_PSYMBOL AliasSeq) is just an alias for its template parameters.
*
- * With $(D_PSYMBOL AliasTuple) it is possible to pass distinguishable
+ * With $(D_PSYMBOL Tuple) it is possible to pass distinguishable
* sequences of parameters to a template. So:
*
* ---
@@ -220,15 +220,15 @@ pure nothrow @safe @nogc unittest
* static assert(Args.length == 2);
* }
*
- * alias BInstance = B!(AliasTuple!(int, uint), AliasTuple!(float, double));
+ * alias BInstance = B!(Tuple!(int, uint), Tuple!(float, double));
* ---
*
* Params:
- * Args = Elements of this $(D_PSYMBOL AliasTuple).
+ * Args = Elements of this $(D_PSYMBOL Tuple).
*
* See_Also: $(D_PSYMBOL AliasSeq).
*/
-template AliasTuple(Args...)
+template Tuple(Args...)
{
/// Elements in this tuple as $(D_PSYMBOL AliasSeq).
alias Seq = Args;
@@ -240,9 +240,9 @@ template AliasTuple(Args...)
///
pure nothrow @safe @nogc unittest
{
- alias A = AliasTuple!(short);
- alias B = AliasTuple!(3, 8, 9);
- alias C = AliasTuple!(A, B);
+ alias A = Tuple!(short);
+ alias B = Tuple!(3, 8, 9);
+ alias C = Tuple!(A, B);
static assert(C.length == 2);
@@ -251,12 +251,176 @@ pure nothrow @safe @nogc unittest
static assert(B.length == 3);
static assert(B.Seq == AliasSeq!(3, 8, 9));
- alias D = AliasTuple!();
+ alias D = Tuple!();
static assert(D.length == 0);
static assert(is(D.Seq == AliasSeq!()));
}
/**
+ * Unordered sequence of unique aliases.
+ *
+ * $(D_PARAM Args) can contain duplicates, but they will be filteredout, so
+ * $(D_PSYMBOL Set) contains only unique items. $(D_PSYMBOL isEqual) is used
+ * for determining if two items are equal.
+ *
+ * Params:
+ * Args = Elements of this $(D_PSYMBOL Tuple).
+ */
+template Set(Args...)
+{
+ /// Elements in this set as $(D_PSYMBOL AliasSeq).
+ alias Seq = NoDuplicates!Args;
+
+ /// The length of the set.
+ enum size_t length = Seq.length;
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ alias S1 = Set!(int, 5, 5, int, 4);
+ static assert(S1.length == 3);
+}
+
+/**
+ * Produces a $(D_PSYMBOL Set) containing all elements of the given
+ * $(D_PARAM Sets).
+ *
+ * Params:
+ * Sets = List of $(D_PSYMBOL Set) instances.
+ *
+ * Returns: Set-theoretic union of all $(D_PARAM Sets).
+ *
+ * See_Also: $(D_PSYMBOL Set).
+ */
+template Union(Sets...)
+if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
+{
+ private template Impl(Sets...)
+ {
+ static if (Sets.length == 0)
+ {
+ alias Impl = AliasSeq!();
+ }
+ else
+ {
+ alias Impl = AliasSeq!(Sets[0].Seq, Impl!(Sets[1 .. $]));
+ }
+ }
+ alias Union = Set!(Impl!Sets);
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ alias S1 = Set!(2, 5, 8, 4);
+ alias S2 = Set!(3, 8, 4, 1);
+ static assert(Union!(S1, S2).Seq == AliasSeq!(2, 5, 8, 4, 3, 1));
+}
+
+/**
+ * Produces a $(D_PSYMBOL Set) that containing elements of
+ * $(D_INLINECODE Sets[0]) that are also elements of all other sets in
+ * $(D_PARAM Sets).
+ *
+ * Params:
+ * Sets = List of $(D_PSYMBOL Set) instances.
+ *
+ * Returns: Set-theoretic intersection of all $(D_PARAM Sets).
+ *
+ * See_Also: $(D_PSYMBOL Set).
+ */
+template Intersection(Sets...)
+if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
+{
+ private template Impl(Args...)
+ if (Args.length > 0)
+ {
+ alias Equal = ApplyLeft!(isEqual, Args[0]);
+ static if (Args.length == 1)
+ {
+ enum bool Impl = true;
+ }
+ else static if (!anySatisfy!(Equal, Args[1].Seq))
+ {
+ enum bool Impl = false;
+ }
+ else
+ {
+ enum bool Impl = Impl!(Args[0], Args[2 .. $]);
+ }
+ }
+
+ private enum bool FilterImpl(Args...) = Impl!(Args[0], Sets[1 .. $]);
+
+ static if (Sets.length == 0)
+ {
+ alias Intersection = Set!();
+ }
+ else
+ {
+ alias Intersection = Set!(Filter!(FilterImpl, Sets[0].Seq));
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ alias S1 = Set!(2, 5, 8, 4);
+ alias S2 = Set!(3, 8, 4, 1);
+ static assert(Intersection!(S1, S2).Seq == AliasSeq!(8, 4));
+
+ static assert(Intersection!(S1).Seq == AliasSeq!(2, 5, 8, 4));
+ static assert(Intersection!().length == 0);
+}
+
+/**
+ * Produces a $(D_PSYMBOL Set) that contains all elements of
+ * $(D_PARAM S1) that are not members of $(D_PARAM S2).
+ *
+ * Params:
+ * S1 = A $(D_PSYMBOL Set).
+ * S2 = A $(D_PSYMBOL Set).
+ *
+ * Returns: Set-theoretic difference of two sets $(D_PARAM S1) and
+ * $(D_PARAM S2).
+ *
+ * See_Also: $(D_PSYMBOL Set).
+ */
+template Difference(alias S1, alias S2)
+if (isInstanceOf!(Set, S1) && isInstanceOf!(Set, S2))
+{
+ private template Impl(Args...)
+ {
+ alias Equal = ApplyLeft!(isEqual, Args[0]);
+ enum bool Impl = !anySatisfy!(Equal, S2.Seq);
+ }
+
+ static if (S1.length == 0)
+ {
+ alias Difference = Set!();
+ }
+ else static if (S2.length == 1)
+ {
+ alias Difference = S1;
+ }
+ else
+ {
+ alias Difference = Set!(Filter!(Impl, S1.Seq));
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ alias S1 = Set!(2, 5, 8, 4);
+ alias S2 = Set!(3, 8, 4, 1);
+ static assert(Difference!(S1, S2).Seq == AliasSeq!(2, 5));
+ static assert(Difference!(S2, S1).Seq == AliasSeq!(3, 1));
+ static assert(Difference!(S1, Set!()).Seq == AliasSeq!(2, 5, 8, 4));
+}
+
+/**
* Tests whether $(D_INLINECODE Args[0]) is less than or equal to
* $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
*
@@ -451,6 +615,9 @@ pure nothrow @safe @nogc unittest
* $(D_INLINECODE is(Args[0] == Args[1])). It it fails, the arguments are
* considered to be not equal.
*
+ * If two items cannot be compared (for example comparing a type with a
+ * number), they are considered not equal.
+ *
* Params:
* Args = Two aliases to compare for equality.
*
@@ -461,7 +628,8 @@ template isEqual(Args...)
if (Args.length == 2)
{
static if ((is(typeof(Args[0] == Args[1])) && (Args[0] == Args[1]))
- || is(Args[0] == Args[1]))
+ || (isTypeTuple!Args && is(Args[0] == Args[1]))
+ || isSame!Args)
{
enum bool isEqual = true;
}
@@ -475,6 +643,8 @@ if (Args.length == 2)
pure nothrow @safe @nogc unittest
{
static assert(isEqual!(int, int));
+ static assert(isEqual!(8, 8));
+ static assert(!isEqual!(int, const(int)));
static assert(!isEqual!(5, int));
static assert(!isEqual!(5, 8));
}
diff --git a/source/tanya/meta/trait.d b/source/tanya/meta/trait.d
index a5e616a..d428ddd 100644
--- a/source/tanya/meta/trait.d
+++ b/source/tanya/meta/trait.d
@@ -416,6 +416,9 @@ version (TanyaPhobos)
EnumMembers,
classInstanceAlignment,
ifTestable,
+ FunctionTypeOf,
+ ReturnType,
+ TemplateOf,
isTypeTuple,
isExpressions;
}
@@ -1873,11 +1876,149 @@ pure nothrow @safe @nogc unittest
}
}
-deprecated("Use tanya.meta.transform.FunctionTypeOf instead")
-alias FunctionTypeOf = tanya.meta.transform.FunctionTypeOf;
+/**
+ * Params:
+ * F = A function.
+ *
+ * Returns: Type of the function $(D_PARAM F).
+ */
+template FunctionTypeOf(F...)
+if (isCallable!F)
+{
+ static if ((is(typeof(F[0]) T : T*) && is(T == function))
+ || (is(F[0] T : T*) && is(T == function))
+ || is(F[0] T == delegate)
+ || is(typeof(F[0]) T == delegate)
+ || is(F[0] T == function)
+ || is(typeof(&F[0]) T == delegate)
+ || (is(typeof(&F[0]) T : T*) && is(T == function)))
+ {
+ alias FunctionTypeOf = T;
+ }
+ else
+ {
+ alias FunctionTypeOf = FunctionTypeOf!(F[0].opCall);
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(is(FunctionTypeOf!(void function()) == function));
+ static assert(is(FunctionTypeOf!(() {}) == function));
+}
+
+private pure nothrow @safe @nogc unittest
+{
+ static assert(is(FunctionTypeOf!(void delegate()) == function));
+
+ static void staticFunc()
+ {
+ }
+ auto functionPointer = &staticFunc;
+ static assert(is(FunctionTypeOf!staticFunc == function));
+ static assert(is(FunctionTypeOf!functionPointer == function));
+
+ void func()
+ {
+ }
+ auto dg = &func;
+ static assert(is(FunctionTypeOf!func == function));
+ static assert(is(FunctionTypeOf!dg == function));
+
+ interface I
+ {
+ @property int prop();
+ }
+ static assert(is(FunctionTypeOf!(I.prop) == function));
+
+ struct S
+ {
+ void opCall()
+ {
+ }
+ }
+ class C
+ {
+ static void opCall()
+ {
+ }
+ }
+ S s;
-deprecated("Use tanya.meta.transform.ReturnType instead")
-alias ReturnType = tanya.meta.transform.ReturnType;
+ static assert(is(FunctionTypeOf!s == function));
+ static assert(is(FunctionTypeOf!C == function));
+ static assert(is(FunctionTypeOf!S == function));
+}
+
+private pure nothrow @safe @nogc unittest
+{
+ struct S2
+ {
+ @property int opCall()
+ {
+ return 0;
+ }
+ }
+ S2 s2;
+ static assert(is(FunctionTypeOf!S2 == function));
+ static assert(is(FunctionTypeOf!s2 == function));
+}
+
+/**
+ * Params:
+ * F = A callable object.
+ *
+ * Returns: Return type of $(D_PARAM F).
+ */
+template ReturnType(F...)
+if (isCallable!F)
+{
+ static if (is(FunctionTypeOf!(F[0]) T == return))
+ {
+ alias ReturnType = T;
+ }
+ else
+ {
+ static assert(false, "Argument is not a callable");
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(is(ReturnType!(int delegate()) == int));
+ static assert(is(ReturnType!(bool function()) == bool));
+}
+
+/**
+ * Determines the template $(D_PARAM T) is an instance of.
+ *
+ * Params:
+ * T = Template instance.
+ *
+ * Returns: Template $(D_PARAM T) is an instance of.
+ */
+alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
+
+///
+pure nothrow @safe @nogc unittest
+{
+ struct S(T)
+ {
+ }
+ static assert(isSame!(TemplateOf!(S!int), S));
+
+ static void func(T)()
+ {
+ }
+ static assert(isSame!(TemplateOf!(func!int), func));
+
+ template T(U)
+ {
+ }
+ static assert(isSame!(TemplateOf!(T!int), T));
+}
/**
* Returns the mangled name of the symbol $(D_PARAM T).
@@ -2392,7 +2533,7 @@ if (isCallable!F)
{
attrs |= FunctionAttribute.shared_;
}
- else static if (a == "system")
+ else static if (a == "@system")
{
attrs |= FunctionAttribute.system;
}
diff --git a/source/tanya/meta/transform.d b/source/tanya/meta/transform.d
index af30aa9..b72fc59 100644
--- a/source/tanya/meta/transform.d
+++ b/source/tanya/meta/transform.d
@@ -6,7 +6,8 @@
* Type transformations.
*
* Templates in this module can be used to modify type qualifiers or transform
- * types.
+ * types. They take some type as argument and return a different type after
+ * perfoming the specified transformation.
*
* Copyright: Eugene Wissner 2017.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
@@ -29,9 +30,6 @@ version (TanyaPhobos)
KeyType,
ValueType,
Promoted,
- FunctionTypeOf,
- ReturnType,
- TemplateOf,
InoutOf,
ConstOf,
SharedOf,
@@ -500,150 +498,6 @@ pure nothrow @safe @nogc unittest
}
/**
- * Params:
- * F = A function.
- *
- * Returns: Type of the function $(D_PARAM F).
- */
-template FunctionTypeOf(F...)
-if (isCallable!F)
-{
- static if ((is(typeof(F[0]) T : T*) && is(T == function))
- || (is(F[0] T : T*) && is(T == function))
- || is(F[0] T == delegate)
- || is(typeof(F[0]) T == delegate)
- || is(F[0] T == function)
- || is(typeof(&F[0]) T == delegate)
- || (is(typeof(&F[0]) T : T*) && is(T == function)))
- {
- alias FunctionTypeOf = T;
- }
- else
- {
- alias FunctionTypeOf = FunctionTypeOf!(F[0].opCall);
- }
-}
-
-///
-pure nothrow @safe @nogc unittest
-{
- static assert(is(FunctionTypeOf!(void function()) == function));
- static assert(is(FunctionTypeOf!(() {}) == function));
-}
-
-private pure nothrow @safe @nogc unittest
-{
- static assert(is(FunctionTypeOf!(void delegate()) == function));
-
- static void staticFunc()
- {
- }
- auto functionPointer = &staticFunc;
- static assert(is(FunctionTypeOf!staticFunc == function));
- static assert(is(FunctionTypeOf!functionPointer == function));
-
- void func()
- {
- }
- auto dg = &func;
- static assert(is(FunctionTypeOf!func == function));
- static assert(is(FunctionTypeOf!dg == function));
-
- interface I
- {
- @property int prop();
- }
- static assert(is(FunctionTypeOf!(I.prop) == function));
-
- struct S
- {
- void opCall()
- {
- }
- }
- class C
- {
- static void opCall()
- {
- }
- }
- S s;
-
- static assert(is(FunctionTypeOf!s == function));
- static assert(is(FunctionTypeOf!C == function));
- static assert(is(FunctionTypeOf!S == function));
-}
-
-private pure nothrow @safe @nogc unittest
-{
- struct S2
- {
- @property int opCall()
- {
- return 0;
- }
- }
- S2 s2;
- static assert(is(FunctionTypeOf!S2 == function));
- static assert(is(FunctionTypeOf!s2 == function));
-}
-
-/**
- * Params:
- * F = A callable object.
- *
- * Returns: Return type of $(D_PARAM F).
- */
-template ReturnType(F...)
-if (isCallable!F)
-{
- static if (is(FunctionTypeOf!(F[0]) T == return))
- {
- alias ReturnType = T;
- }
- else
- {
- static assert(false, "Argument is not a callable");
- }
-}
-
-///
-pure nothrow @safe @nogc unittest
-{
- static assert(is(ReturnType!(int delegate()) == int));
- static assert(is(ReturnType!(bool function()) == bool));
-}
-
-/**
- * Determines the template $(D_PARAM T) is an instance of.
- *
- * Params:
- * T = Template instance.
- *
- * Returns: Template $(D_PARAM T) is an instance of.
- */
-alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
-
-///
-pure nothrow @safe @nogc unittest
-{
- struct S(T)
- {
- }
- static assert(isSame!(TemplateOf!(S!int), S));
-
- static void func(T)()
- {
- }
- static assert(isSame!(TemplateOf!(func!int), func));
-
- template T(U)
- {
- }
- static assert(isSame!(TemplateOf!(T!int), T));
-}
-
-/**
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
*
* Params: