From 7e93bcdeeb985e900bfc4f5a0f87fca5d09a3850 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 4 Oct 2017 06:06:26 +0200 Subject: [PATCH] meta: Add canFind and isInnerClass --- source/tanya/meta/metafunction.d | 35 ++++++++++++++++++-- source/tanya/meta/trait.d | 56 ++++++++++++++++++++++++++++++-- 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). */ @@ -910,6 +910,37 @@ pure nothrow @safe @nogc unittest static assert(staticIndexOf!(3, () {}, uint, 5, 3) == 3); } +/** + * 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)); +}