www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How do you test whether a variable is static or not?

reply Jonathan M Davis via Digitalmars-d-learn writes:
I'm writing some serialization code where I need to skip static variables.
So, I have a symbol from a struct, and I'd like to test whether it's static
or not. Ideally, I'd be able to do something like

is(field == static)

but of course that doesn't work. There is __traits(isStaticFunction, ...),
but there is no __traits(isStaticVariable, ...) or __traits(isStatic, ...),
and I don't see anything in std.traits which would help. The closest that
I've been able to come up with is

template isStaticVar(T, alias field)
{
    enum isStaticVar =
        is(typeof({mixin("auto i = T." ~ field.stringof ~ ";");}));
}

For a more general solution, it would of course need to verify that the
field wasn't a function as well, but in my case, that was already checked
prior to instantiating isStaticVar, so I can skip it here. And what I have
mostly works. However, it would fail miserably if the field were a static
member variable that was non-copyable. If it were, then that code would
would declare it to be non-static. Now, non-copyable structs are rare enough
that I can probably get away with letting that bug stand, but I'd prefer to
correctly detect whether a variable is static or not. Does anyone have a
better idea of how to do this?

- Jonathan M Davis
Jul 30 2016
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 07/30/2016 05:47 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
 I'm writing some serialization code where I need to skip static 
variables.
 So, I have a symbol from a struct, and I'd like to test whether it's 
static
 or not.
static variables don't have the .offsetof property: struct S { int a; static int b; } // Bonus question: should field be alias or string? template isStaticVar(T, alias field) { enum isStaticVar = !__traits(compiles, mixin("T." ~ field ~ ".offsetof")); } void main() { static assert (!isStaticVar!(S, "a")); static assert (isStaticVar!(S, "b")); } Ali
Jul 30 2016
next sibling parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 30 July 2016 at 13:04:56 UTC, Ali Çehreli wrote:
 On 07/30/2016 05:47 AM, Jonathan M Davis via 
 Digitalmars-d-learn wrote:
 I'm writing some serialization code where I need to skip
static variables.
 So, I have a symbol from a struct, and I'd like to test
whether it's static
 or not.
static variables don't have the .offsetof property: struct S { int a; static int b; } // Bonus question: should field be alias or string? template isStaticVar(T, alias field) { enum isStaticVar = !__traits(compiles, mixin("T." ~ field ~ ".offsetof")); } void main() { static assert (!isStaticVar!(S, "a")); static assert (isStaticVar!(S, "b")); } Ali
Wow, this is directly for std.traits !
Jul 30 2016
prev sibling next sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Saturday, July 30, 2016 06:04:56 Ali Çehreli via Digitalmars-d-learn wrote:
 On 07/30/2016 05:47 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
  > I'm writing some serialization code where I need to skip static

 variables.

  > So, I have a symbol from a struct, and I'd like to test whether it's

 static

  > or not.

 static variables don't have the .offsetof property:

 struct S {
      int a;
      static int b;

 // Bonus question: should field be alias or string?
That depends on what you're doing. __traits(allMembers, ...) gives you a list of strings, so it may make more sense in the general case to use string, but in order to actually do much of anything useful, you have to convert them all to symbols, which is what I've done in my code and why I was using an alias.
 template isStaticVar(T, alias field)
 {
      enum isStaticVar = !__traits(compiles, mixin("T." ~ field ~
 ".offsetof"));
 }

 void main() {
      static assert (!isStaticVar!(S, "a"));
      static assert (isStaticVar!(S, "b"));
 }
Thanks! - Jonathan M Davis
Jul 30 2016
prev sibling parent reply DigitalDesigns <DigitalDesigns gmail.com> writes:
On Saturday, 30 July 2016 at 13:04:56 UTC, Ali Çehreli wrote:
 On 07/30/2016 05:47 AM, Jonathan M Davis via 
 Digitalmars-d-learn wrote:
 I'm writing some serialization code where I need to skip
static variables.
 So, I have a symbol from a struct, and I'd like to test
whether it's static
 or not.
static variables don't have the .offsetof property: struct S { int a; static int b; } // Bonus question: should field be alias or string? template isStaticVar(T, alias field) { enum isStaticVar = !__traits(compiles, mixin("T." ~ field ~ ".offsetof")); } void main() { static assert (!isStaticVar!(S, "a")); static assert (isStaticVar!(S, "b")); } Ali
This doesn't work, treats fields in base classes as static. One way to test if a member is static is if it it doesn't exist in tupleof... but this only returns the immediate members and so will fail. I guess one will have to check all base types too and if it doesn't exist in any of then it should be static. Why is it so hard to be able to get basic information like if a type is static or not?
Jun 16 2018
parent Bauss <jj_1337 live.dk> writes:
On Saturday, 16 June 2018 at 08:52:20 UTC, DigitalDesigns wrote:
 On Saturday, 30 July 2016 at 13:04:56 UTC, Ali Çehreli wrote:
 On 07/30/2016 05:47 AM, Jonathan M Davis via 
 Digitalmars-d-learn wrote:
 I'm writing some serialization code where I need to skip
static variables.
 So, I have a symbol from a struct, and I'd like to test
whether it's static
 or not.
static variables don't have the .offsetof property: struct S { int a; static int b; } // Bonus question: should field be alias or string? template isStaticVar(T, alias field) { enum isStaticVar = !__traits(compiles, mixin("T." ~ field ~ ".offsetof")); } void main() { static assert (!isStaticVar!(S, "a")); static assert (isStaticVar!(S, "b")); } Ali
This doesn't work, treats fields in base classes as static. One way to test if a member is static is if it it doesn't exist in tupleof... but this only returns the immediate members and so will fail. I guess one will have to check all base types too and if it doesn't exist in any of then it should be static. Why is it so hard to be able to get basic information like if a type is static or not?
Probably because the symbols don't carry the information. I'd reckon a compiler addition to __traits() would probably solve this. Something like getStaticMembers
Jun 16 2018
prev sibling next sibling parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 30 July 2016 at 12:47:10 UTC, Jonathan M Davis wrote:
 I'm writing some serialization code where I need to skip static 
 variables. So, I have a symbol from a struct, and I'd like to 
 test whether it's static or not. Ideally, I'd be able to do 
 something like

 is(field == static)

 but of course that doesn't work. There is 
 __traits(isStaticFunction, ...),
 but there is no __traits(isStaticVariable, ...) or 
 __traits(isStatic, ...),
 and I don't see anything in std.traits which would help. The 
 closest that
 I've been able to come up with is

 template isStaticVar(T, alias field)
 {
     enum isStaticVar =
         is(typeof({mixin("auto i = T." ~ field.stringof ~ 
 ";");}));
 }

 For a more general solution, it would of course need to verify 
 that the field wasn't a function as well, but in my case, that 
 was already checked prior to instantiating isStaticVar, so I 
 can skip it here. And what I have mostly works. However, it 
 would fail miserably if the field were a static member variable 
 that was non-copyable. If it were, then that code would would 
 declare it to be non-static. Now, non-copyable structs are rare 
 enough that I can probably get away with letting that bug 
 stand, but I'd prefer to correctly detect whether a variable is 
 static or not. Does anyone have a better idea of how to do this?

 - Jonathan M Davis
You won't be able to assign it if it's not static. Given this isStaticVar(Stuff) = __traits(compiles, Stuff = typeof(Stuff).init)) Unfortuantely it's hard to make a stand alone template for this. For example I was not able to verify the non-static case struct Foo { static int a; int b; } template isStaticVar(alias stuff) { bool check() { bool result; static if (!is(typeof(__traits(parent, stuff)))) result = true; else static if (__traits(compiles, stuff = typeof(stuff).init)) result = true; return result; } enum isStaticVar = check(); } unittest { static assert(isStaticVar!(Foo.a)); //static assert(isStaticVar!(Foo.b)); } I'm curious to see the other solutions.
Jul 30 2016
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 7/30/16 8:47 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
 I'm writing some serialization code where I need to skip static variables.
 So, I have a symbol from a struct, and I'd like to test whether it's static
 or not. Ideally, I'd be able to do something like
 
 is(field == static)
std.traits.hasStaticMember ? https://dlang.org/phobos/std_traits.html#hasStaticMember -Steve
Jun 16 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 16, 2018 14:55:51 Steven Schveighoffer via Digitalmars-d-
learn wrote:
 On 7/30/16 8:47 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
 I'm writing some serialization code where I need to skip static
 variables. So, I have a symbol from a struct, and I'd like to test
 whether it's static or not. Ideally, I'd be able to do something like

 is(field == static)
std.traits.hasStaticMember ? https://dlang.org/phobos/std_traits.html#hasStaticMember
Yeah. I wrote that, and it got added to Phobos. If you'll note, my post in this thread was from almost two years ago. - Jonathan M Davis
Jun 16 2018
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On Saturday, 16 June 2018 at 21:41:37 UTC, Jonathan M Davis wrote:
 On Saturday, June 16, 2018 14:55:51 Steven Schveighoffer via 
 Digitalmars-d- learn wrote:
 On 7/30/16 8:47 AM, Jonathan M Davis via Digitalmars-d-learn 
 wrote:
 I'm writing some serialization code where I need to skip 
 static variables. So, I have a symbol from a struct, and I'd 
 like to test whether it's static or not. Ideally, I'd be 
 able to do something like

 is(field == static)
std.traits.hasStaticMember ? https://dlang.org/phobos/std_traits.html#hasStaticMember
Yeah. I wrote that, and it got added to Phobos. If you'll note, my post in this thread was from almost two years ago.
Haha! I usually don’t get caught with these old threads! -Steve
Jun 16 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 16, 2018 22:11:09 Steven Schveighoffer via Digitalmars-d-
learn wrote:
 On Saturday, 16 June 2018 at 21:41:37 UTC, Jonathan M Davis wrote:
 On Saturday, June 16, 2018 14:55:51 Steven Schveighoffer via

 Digitalmars-d- learn wrote:
 On 7/30/16 8:47 AM, Jonathan M Davis via Digitalmars-d-learn

 wrote:
 I'm writing some serialization code where I need to skip
 static variables. So, I have a symbol from a struct, and I'd
 like to test whether it's static or not. Ideally, I'd be
 able to do something like

 is(field == static)
std.traits.hasStaticMember ? https://dlang.org/phobos/std_traits.html#hasStaticMember
Yeah. I wrote that, and it got added to Phobos. If you'll note, my post in this thread was from almost two years ago.
Haha! I usually don’t get caught with these old threads!
It's _really_ obvious in my e-mail reader, since I have threading turned on, and it the threads are sorted by the date of the first post in the thread, so the thread is way up in the list such that I'm only likely to even notice that such a post has been made if I tell my client to filter out read e-mails so that I can find the e-mails that I haven't read yet which aren't at the bottom where all of the recent stuff is. Someone could have replied in an old thread and really want me to respond, and I could easily not notice the message for weeks if I'm not trying to get the unread count down to zero and notice that once I've caught up with all of the recent messages, the number is still greater than zero. I kind of wish that the forum software discouraged against necro-ing threads like this, since they're easy for many of us to miss, and once someone replies to them and brings them to the front of the list in the forum software, folks tends to reply as if the thread were recent without noticing how old it is. - Jonathan M Davis
Jun 16 2018
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/16/18 6:23 PM, Jonathan M Davis wrote:
 I kind of wish that the forum software discouraged against necro-ing threads
 like this, since they're easy for many of us to miss, and once someone
 replies to them and brings them to the front of the list in the forum
 software, folks tends to reply as if the thread were recent without noticing
 how old it is.
There is somewhat of a colorization of the date based on the age, but it's not drastic enough for ancient threads, and it's not as obvious as it would be if, say, the whole line was colored differently. -Steve
Jun 17 2018
prev sibling parent reply DigitalDesigns <DigitalDesigns gmail.com> writes:
On Saturday, 16 June 2018 at 21:41:37 UTC, Jonathan M Davis wrote:
 On Saturday, June 16, 2018 14:55:51 Steven Schveighoffer via 
 Digitalmars-d- learn wrote:
 On 7/30/16 8:47 AM, Jonathan M Davis via Digitalmars-d-learn 
 wrote:
 I'm writing some serialization code where I need to skip 
 static variables. So, I have a symbol from a struct, and I'd 
 like to test whether it's static or not. Ideally, I'd be 
 able to do something like

 is(field == static)
std.traits.hasStaticMember ? https://dlang.org/phobos/std_traits.html#hasStaticMember
Yeah. I wrote that, and it got added to Phobos. If you'll note, my post in this thread was from almost two years ago. - Jonathan M Davis
doesn't work: ..\..\src\phobos\std\traits.d(3823): Error: class `app.A` member `z` is not accessible. What is the point of introspection if one can't get information about a type due to it's protection level? For example, how is one suppose to serialize a class that has protected and private members, which are common, when using properties?
Jun 16 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 16, 2018 22:56:38 DigitalDesigns via Digitalmars-d-learn 
wrote:
 On Saturday, 16 June 2018 at 21:41:37 UTC, Jonathan M Davis wrote:
 On Saturday, June 16, 2018 14:55:51 Steven Schveighoffer via

 Digitalmars-d- learn wrote:
 On 7/30/16 8:47 AM, Jonathan M Davis via Digitalmars-d-learn

 wrote:
 I'm writing some serialization code where I need to skip
 static variables. So, I have a symbol from a struct, and I'd
 like to test whether it's static or not. Ideally, I'd be
 able to do something like

 is(field == static)
std.traits.hasStaticMember ? https://dlang.org/phobos/std_traits.html#hasStaticMember
Yeah. I wrote that, and it got added to Phobos. If you'll note, my post in this thread was from almost two years ago. - Jonathan M Davis
doesn't work: ..\..\src\phobos\std\traits.d(3823): Error: class `app.A` member `z` is not accessible. What is the point of introspection if one can't get information about a type due to it's protection level? For example, how is one suppose to serialize a class that has protected and private members, which are common, when using properties?
The fact that you can't introspect on private variables with stuff like __traits is a well-known bug, and I expect that it will be fixed at some point. But if it's serialization that you want, then as I understand it, tupleof should work to get at the direct fields of a struct or class even if they're private. And you can always look at what a serialization library like Orange did. - Jonathan M Davis
Jun 16 2018