From d79da1d3cac16043b3599a234875c20c9a9e7b0c Mon Sep 17 00:00:00 2001 From: sprinkle131313 Date: Fri, 10 Feb 2017 02:42:52 -0500 Subject: [PATCH] Issue 16485 - Add trait for testing if a member is static. --- changelog/std-traits-hasStaticMember.dd | 13 ++ std/traits.d | 177 ++++++++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 changelog/std-traits-hasStaticMember.dd diff --git a/changelog/std-traits-hasStaticMember.dd b/changelog/std-traits-hasStaticMember.dd new file mode 100644 index 000000000..dfd536b08 --- /dev/null +++ b/changelog/std-traits-hasStaticMember.dd @@ -0,0 +1,13 @@ +Added `std.traits.hasStaticMember` to check whether a symbol is a static member of a type. +------- +import std.traits : hasStaticMember; + +struct S +{ + static int globalVar; + int localVar; +} + +assert( hasStaticMember!(S, "globalVar")); +assert(!hasStaticMember!(S, "localVar")); +------- diff --git a/std/traits.d b/std/traits.d index 3384707f6..0af4799ef 100644 --- a/std/traits.d +++ b/std/traits.d @@ -44,6 +44,7 @@ * $(LREF hasElaborateDestructor) * $(LREF hasIndirections) * $(LREF hasMember) + * $(LREF hasStaticMember) * $(LREF hasNested) * $(LREF hasUnsharedAliasing) * $(LREF InterfacesTuple) @@ -3553,6 +3554,182 @@ enum hasMember(T, string name) = __traits(hasMember, T, name); static assert(hasMember!(S, "foo")); } +/** + * Whether the symbol represented by the string, member, exists and is a static member of T. + * + * Params: + * T = Type containing symbol $(D member). + * member = Name of symbol to test that resides in $(D T). + * + * Returns: + * $(D true) iff $(D member) exists and is static. + */ +template hasStaticMember(T, string member) +{ + static if (__traits(hasMember, T, member)) + { + import std.meta : Alias; + alias sym = Alias!(__traits(getMember, T, member)); + + static if (__traits(getOverloads, T, member).length == 0) + enum bool hasStaticMember = __traits(compiles, &sym); + else + enum bool hasStaticMember = __traits(isStaticFunction, sym); + } + else + { + enum bool hasStaticMember = false; + } +} + +/// +@safe unittest +{ + static struct S + { + static void sf() {} + void f() {} + + static int si; + int i; + } + + static assert( hasStaticMember!(S, "sf")); + static assert(!hasStaticMember!(S, "f")); + + static assert( hasStaticMember!(S, "si")); + static assert(!hasStaticMember!(S, "i")); + + static assert(!hasStaticMember!(S, "hello")); +} + +@safe unittest +{ + static struct S + { + enum X = 10; + enum Y + { + i = 10 + } + struct S {} + class C {} + + static int sx = 0; + __gshared int gx = 0; + + Y y; + static Y sy; + + static void f(); + static void f2() pure nothrow @nogc @safe; + + shared void g(); + + static void function() fp; + __gshared void function() gfp; + void function() fpm; + + void delegate() dm; + static void delegate() sd; + + void m(); + final void m2() const pure nothrow @nogc @safe; + + inout(int) iom() inout; + static inout(int) iosf(inout int x); + + @property int p(); + static @property int sp(); + } + + static class C + { + enum X = 10; + enum Y + { + i = 10 + } + struct S {} + class C {} + + static int sx = 0; + __gshared int gx = 0; + + Y y; + static Y sy; + + static void f(); + static void f2() pure nothrow @nogc @safe; + + shared void g() { } + + static void function() fp; + __gshared void function() gfp; + void function() fpm; + + void delegate() dm; + static void delegate() sd; + + void m() {} + final void m2() const pure nothrow @nogc @safe; + + inout(int) iom() inout { return 10; } + static inout(int) iosf(inout int x); + + @property int p() { return 10; } + static @property int sp(); + } + + static assert(!hasStaticMember!(S, "X")); + static assert(!hasStaticMember!(S, "Y")); + static assert(!hasStaticMember!(S, "Y.i")); + static assert(!hasStaticMember!(S, "S")); + static assert(!hasStaticMember!(S, "C")); + static assert( hasStaticMember!(S, "sx")); + static assert( hasStaticMember!(S, "gx")); + static assert(!hasStaticMember!(S, "y")); + static assert( hasStaticMember!(S, "sy")); + static assert( hasStaticMember!(S, "f")); + static assert( hasStaticMember!(S, "f2")); + static assert(!hasStaticMember!(S, "dm")); + static assert( hasStaticMember!(S, "sd")); + static assert(!hasStaticMember!(S, "g")); + static assert( hasStaticMember!(S, "fp")); + static assert( hasStaticMember!(S, "gfp")); + static assert(!hasStaticMember!(S, "fpm")); + static assert(!hasStaticMember!(S, "m")); + static assert(!hasStaticMember!(S, "m2")); + static assert(!hasStaticMember!(S, "iom")); + static assert( hasStaticMember!(S, "iosf")); + static assert(!hasStaticMember!(S, "p")); + static assert( hasStaticMember!(S, "sp")); + + static assert(!hasStaticMember!(C, "X")); + static assert(!hasStaticMember!(C, "Y")); + static assert(!hasStaticMember!(C, "Y.i")); + static assert(!hasStaticMember!(C, "S")); + static assert(!hasStaticMember!(C, "C")); + static assert( hasStaticMember!(C, "sx")); + static assert( hasStaticMember!(C, "gx")); + static assert(!hasStaticMember!(C, "y")); + static assert( hasStaticMember!(C, "sy")); + static assert( hasStaticMember!(C, "f")); + static assert( hasStaticMember!(C, "f2")); + static assert(!hasStaticMember!(S, "dm")); + static assert( hasStaticMember!(S, "sd")); + static assert(!hasStaticMember!(C, "g")); + static assert( hasStaticMember!(C, "fp")); + static assert( hasStaticMember!(C, "gfp")); + static assert(!hasStaticMember!(C, "fpm")); + static assert(!hasStaticMember!(C, "m")); + static assert(!hasStaticMember!(C, "m2")); + static assert(!hasStaticMember!(C, "iom")); + static assert( hasStaticMember!(C, "iosf")); + static assert(!hasStaticMember!(C, "p")); + static assert( hasStaticMember!(C, "sp")); +} + /** Retrieves the members of an enumerated type $(D enum E).