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 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 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