summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-10-04 06:06:26 +0200
committerEugen Wissner <belka@caraus.de>2017-10-04 06:06:26 +0200
commit7e93bcdeeb985e900bfc4f5a0f87fca5d09a3850 (patch)
tree9e030e5b7306a5b8edaa6129be7f2b5ec4eb9d35
parente4cd57a61543833c00b3e6a7254962b385db5ef2 (diff)
downloadtanya-7e93bcdeeb985e900bfc4f5a0f87fca5d09a3850.tar.gz
meta: Add canFind and isInnerClass
-rw-r--r--source/tanya/meta/metafunction.d35
-rw-r--r--source/tanya/meta/trait.d56
2 files changed, 87 insertions, 4 deletions
diff --git a/source/tanya/meta/metafunction.d b/source/tanya/meta/metafunction.d
index ccaa89e..e126ed3 100644
--- a/source/tanya/meta/metafunction.d
+++ b/source/tanya/meta/metafunction.d
@@ -885,8 +885,8 @@ if (Args.length > 0)
* `-1` is returned if $(D_PARAM T) is not found.
*
* Params:
- * T = The type to search for.
- * L = Type list.
+ * T = The item to search for.
+ * L = Symbol sequence.
*
* Returns: The index of the first occurrence of $(D_PARAM T) in $(D_PARAM L).
*/
@@ -911,6 +911,37 @@ pure nothrow @safe @nogc unittest
}
/**
+ * Looks for $(D_PARAM T) in $(D_PARAM L) and returns $(D_KEYWORD true) if it
+ * could be found and $(D_KEYWORD false) otherwise.
+ *
+ * Params:
+ * T = The item to search for.
+ * L = Symbol sequence.
+ *
+ * Returns: $(D_KEYWORD true) if $(D_PARAM T) can be found in $(D_PARAM L),
+ * $(D_KEYWORD false) otherwise.
+ */
+template canFind(T, L...)
+{
+ enum bool canFind = indexOf!(0, AliasSeq!(T, L)) != -1;
+}
+
+/// ditto
+template canFind(alias T, L...)
+{
+ enum bool canFind = indexOf!(0, AliasSeq!(T, L)) != -1;
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ static assert(!canFind!(int));
+ static assert(canFind!(int, int));
+ static assert(canFind!(int, float, double, int, real));
+ static assert(canFind!(3, () {}, uint, 5, 3));
+}
+
+/**
* Combines multiple templates with logical AND. So $(D_PSYMBOL templateAnd)
* evaluates to $(D_INLINECODE Preds[0] && Preds[1] && Preds[2]) and so on.
*
diff --git a/source/tanya/meta/trait.d b/source/tanya/meta/trait.d
index eb48cb5..bf46fb3 100644
--- a/source/tanya/meta/trait.d
+++ b/source/tanya/meta/trait.d
@@ -660,8 +660,12 @@ enum bool isBasicType(T) = isScalarType!T || is(T : void);
///
pure nothrow @safe @nogc unittest
{
- struct S;
- class C;
+ static struct S
+ {
+ }
+ class C
+ {
+ }
enum E : int
{
i = 0,
@@ -2996,3 +3000,51 @@ pure nothrow @safe @nogc unittest
static assert(hasUDA!(a, Attr1));
static assert(!hasUDA!(a, Attr2));
}
+
+/**
+ * Tests whether $(D_PARAM T) is an inner class, i.e. a class nested inside
+ * another class.
+ *
+ * All inner classes get `outer` propery automatically generated, which points
+ * to its parent class, though it can be explicitly defined to be something
+ * different. If $(D_PARAM T) does this, $(D_PSYMBOL isInnerClass)
+ * evaluates to $(D_KEYWORD false).
+ *
+ * Params:
+ * T = Class to be tested.
+ *
+ * Returns $(D_KEYWORD true) if $(D_PARAM T) is an inner class,
+ * $(D_KEYWORD false) otherwise.
+ */
+template isInnerClass(T)
+{
+ static if (is(T == class) && is(Alias!(__traits(parent, T)) == class))
+ {
+ enum bool isInnerClass = !canFind!("outer", __traits(allMembers, T));
+ }
+ else
+ {
+ enum bool isInnerClass = false;
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ class A
+ {
+ }
+ class O
+ {
+ class I
+ {
+ }
+ class Fake
+ {
+ bool outer;
+ }
+ }
+ static assert(!isInnerClass!(O));
+ static assert(isInnerClass!(O.I));
+ static assert(!isInnerClass!(O.Fake));
+}