-
-
Notifications
You must be signed in to change notification settings - Fork 747
Issue 16485 - Add trait for testing if a member is static. #5112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| Added `std.traits.hasStaticMember` to check whether a symbol is a static member of a type. | ||
|
|
||
| ------- | ||
| import std.traits : hasStaticMember; | ||
|
|
||
| struct S | ||
| { | ||
| static int staticVar; | ||
| int nonstaticVar; | ||
| } | ||
|
|
||
| assert( hasStaticMember!(S, "staticVar")); | ||
| assert(!hasStaticMember!(S, "nonstaticVar")); | ||
| ------- | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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; } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't define a body when you don't call it as it will lead to coverage errors ;-)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those ones caused link errors in the test build if they aren't there. For reference, the related error'd build: https://circleci.com/gh/dlang/phobos/2050 |
||
| 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). | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andralex while the current changelog parser is very forgiving, we should probably make a decision on the format:
(A) is implemented as dlang/tools#220
(B) is how our parser works currently.
Personally I am quite happy with closing the PR and agreeing that a title can't be more than one line (doesn't make much sense anyways).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll let @CyberShadow decide, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any deciding arguments one way or another.
I think enforcing that the second line is blank would be good to avoid accidental ambiguity, and would follow formatting for git commit messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: start with a more restrictive policy then relax it as experience develops. The other way is much more difficult, as we've all learned the hard way :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sprinkle131313 as we seem to have reached a consensus here, would you be so kind to insert an empty line after the title?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wilzbach how do we use that nice relatively new feature of github allowing others to amend someone's pull request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR author needs to opt in, which it doesn't look like they've done here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://wiki.dlang.org/Guidelines_for_maintainers#Write_access_to_PRs
It's enabled here:
Anyways we put this into the reminder message of the DLang-Bot:
dlang/dlang-bot#44
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, oops, I was looking in the wrong place.