Skip to content

Conversation

@jmdavis
Copy link
Member

@jmdavis jmdavis commented Oct 3, 2016

isStaticMember tests whether a member of a struct or class is static or
not. It works with both functions and variables.

This has come up several times lately, and it definitely seems like we need something like this in std.traits. Technically, issue# 16485 is for adding a trait for testing for a static variable whereas this works with both functions and variables, but they should be distinguishable via __traits(isStaticFunction, ...). The most recent discussion on this is

http://forum.dlang.org/post/mailman.810.1475501243.2994.digitalmars-d@puremagic.com

The tests are a slightly expanded version of what Manu proposed there.

@Temtaime
Copy link
Contributor

Temtaime commented Oct 3, 2016

template isStaticMember(T, string member) if (__traits(hasMember, T, member))

Seems better

std/traits.d Outdated

static if (__traits(isStaticFunction, sym))
enum bool isStaticMember = true;
else static if (is(FunctionTypeOf!sym == function) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap the other checks inside a static if(is(sym == function)) to avoid templates for the most common case.

@jmdavis jmdavis force-pushed the isStaticMember branch 2 times, most recently from 992dbb8 to 1d9b6b9 Compare October 4, 2016 02:54
@jmdavis
Copy link
Member Author

jmdavis commented Oct 4, 2016

Okay. I updated the code per the comments here and in the newsgroup.

static if (is(typeof(sym) == function) || is(FunctionTypeOf!(typeof(&sym)) == function))
enum bool isStaticMember = __traits(isStaticFunction, sym);
else
enum bool isStaticMember = __traits(compiles, &sym);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use compiles instead of is(typeof(&sym))?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that it matters in this case, but there are subtle differences between the two, and I've been advised in the past to favor __traits(compiles, ...). If I understand correctly, the main difference is that __traits(compiles, ...) actually checks for compilation, whereas is(typeof(...)) just checks that the type exists (e.g. there was a discussion on it here with Don: https://issues.dlang.org/show_bug.cgi?id=8339 ). __traits(compiles, ...) is also more explicit about what you're doing. So, I generally try to use __traits(compiles, ...) instead of is(typeof(...)). I confess though that I don't understand the subtleties well enough to know when it really matters.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like a weird recommendation. I wonder if there is a compiler workload difference?
I have a very poor feel for what things the compiler does quickly, and which are high-impact on compile time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Andrei was the one who recommended the traits option to me, so you can probably ask him

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TurkeyMan there is almost no difference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In cases where this does hit your compile times you need a high n.
In such cases template instanciation cost will shadow everything else.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does 'accurate' mean? I've seen a bunch of weird recommendations emerging... they're not written anywhere. Are people just supposed to know?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TurkeyMan It's more or less folk knowledge that's passed around. I don't think it's documented anywhere other than various forum threads. That said, it is definitely better to use __traits(compiles).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more or less folk knowledge that's passed around.

Right, and that's absolutely not okay! We're meant to be attracting new users. The meta experience is D's main offering, and new users should be able to get working and feel powerful with as little friction as possible. "Oh, yeah that obvious thing to type isn't actually what you do, you need to do this awkward unintuitive thing instead" is not something that's okay to say to new users.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not claiming it's obvious or ideal 😉 Just letting you know how things are.

isStaticMember tests whether a member of a struct or class is static or
not. It works with both functions and variables.
@jmdavis
Copy link
Member Author

jmdavis commented Oct 8, 2016

I figured out how to make FunctionTypeOf unnecessary and make it even shorter (by using __traits(getOverloads, ...)), so I just updated the PR with that change. In spite of the surprising amount of effort required to figure out how to do this right, the actual implementation has gotten to the point that it's quite simple.

Copy link
Member

@PetarKirov PetarKirov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

Copy link
Contributor

@TurkeyMan TurkeyMan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@JackStouffer
Copy link
Contributor

Needs a changelog entry

@JackStouffer
Copy link
Contributor

JackStouffer commented Oct 26, 2016

Wait, __gshared functions don't have context pointers but shared functions do? I don't see any hard info in the spec on what __gshared means for member functions so any clarification would be appreciated.

@aG0aep6G
Copy link
Contributor

Wait, __gshared functions don't have context pointers but shared functions do? I don't see any hard info in the spec on what __gshared means for member functions so any clarification would be appreciated.

http://dlang.org/spec/attribute.html#gshared: "__gshared may also be applied to member variables and local variables. In these cases, __gshared is equivalent to static, except that the variable is shared by all threads rather than being thread local."

In contrast, shared does not imply static.

@JackStouffer
Copy link
Contributor

_gshared may also be applied to member variables and local variables. In these cases, __gshared is equivalent to static, except that the variable is shared by all threads rather than being thread local.

Ok thanks.

Also, what's the reason to use strings to do isStaticMember(S, "g") rather than isStaticMember(S.g)?

@jmdavis
Copy link
Member Author

jmdavis commented Oct 27, 2016

Also, what's the reason to use strings to do isStaticMember(S, "g") rather than isStaticMember(S.g)?

Because that's what you get from __traits(allMembers, T).


/++
Whether the symbol represented by the string, member, is a static member of
T.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs params and returns

@wilzbach
Copy link
Contributor

Needs a changelog entry

This will be automatically generated if it's detected by the Dlang Bot.

@jmdavis if you remove # from the commit message the Dlang Bot can detect it. Also if you use close or other it can do more magic, so instead of:

Implement issue# 16485 ...

this would allow it to do it's magic (auto-linking, closing, adding to the changelog):

Fix issue 16485 ...

@wilzbach
Copy link
Contributor

Closing as @sprinkle131313 has "revived" this at #5112

@wilzbach wilzbach closed this Feb 17, 2017
@jmdavis jmdavis deleted the isStaticMember branch May 5, 2017 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants