www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Weird behavior with UDAs

reply realhet <real_het hotmail.com> writes:
Hello, I have a problem I can't even understand with the code 
below:

https://run.dlang.io/is/7yXAEA

import std.stdio, std.range, std.algorithm, std.traits, std.meta;

struct UNIFORM{ string name; }

struct A{
     int i1;
      UNIFORM() int i2;
      UNIFORM("fuzz") int i3;
      UNIFORM int i4;
}

template getUDA(alias a, U){
   static if(hasUDA!(a, U)) enum getUDA = getUDAs!(a, U)[$-1];
                       else enum getUDA = U.init;
}

pragma(msg, getUDA!(A.i1, UNIFORM)); //UNIFORM(null)
pragma(msg, getUDA!(A.i2, UNIFORM)); //UNIFORM(null)
pragma(msg, getUDA!(A.i3, UNIFORM)); //UNIFORM("fuzz");
pragma(msg, getUDA!(A.i4, UNIFORM)); //Error: initializer must be 
an expression, not UNIFORM

struct UNIFORM2{ string name=""; }
struct B{  UNIFORM2() int i1; }

pragma(msg, getUDA!(B.i1, UNIFORM2)); //UNIFORM("") instead if 
UNIFORM(null)

//------------------------------------------------------------------------

My first question is, how to avoid that error with A.i4?  Why is 
there a difference between  UNIFORM and  UNIFORM(), do the first 
returns a type and the later returns a value?

My second quertion is, why the UNIFORM struct with uninitialized 
string producing UNIFORM(null).
How can be a difference when I say name="", and it's just the 
same as the default string initializer, and then it produce 
UNIFORM("")?

Thank You!
Jun 13 2020
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 13 June 2020 at 12:55:36 UTC, realhet wrote:
 My first question is, how to avoid that error with A.i4?  Why 
 is there a difference between  UNIFORM and  UNIFORM(), do the 
 first returns a type and the later returns a value?
Basically yeah. a UDA in D is just whatever you write gets directly attached - it does no additional processing. So if you give it a type, it keeps a type. If a value, it keeps the value. The simplest answer is probably "don't do that"; if it is meant to be a value, always give it a value. But you could also write your own get UDA thing that recognizes the type (the check: static if(is(attribute)) for a type vs static if(is(typeof(attribute))) for the value) and returns the init value if you want in your code.
 My second quertion is, why the UNIFORM struct with 
 uninitialized string producing UNIFORM(null).
 How can be a difference when I say name="", and it's just the 
 same as the default string initializer, and then it produce 
 UNIFORM("")?
null and "" can be used interchangeably and sometimes yield the same thing, but they aren't exactly the same. Since you specified it there in the definition as a default value in a struct the compiler used that distinction. I'd suggest you write what you mean even in cases where it is the same so you cover the bases. If you specifically want null, check `str is null` and use ` = null`. If either is fine, just use `str.length == 0`.
Jun 13 2020
prev sibling parent reply realhet <real_het hotmail.com> writes:
On Saturday, 13 June 2020 at 12:55:36 UTC, realhet wrote:
 Hello, I have a problem I can't even understand with the code
For the first I realized that an UDA can be a type too, and come up with this: template getUDA(alias a, U){ enum u = q{ getUDAs!(a, U)[$-1] }; static if(hasUDA!(a, U) && !is(mixin(u))) enum getUDA = mixin(u); else enum getUDA = U.init; } So I always get an instance of the UDA with the default values. But the second question is still beyond me: How can be a string represented with 'null' by default instead on `""`. Unless I state it explicitly with name="" ? o.O
Jun 13 2020
parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 13 June 2020 at 13:08:29 UTC, realhet wrote:

 How can be a string represented with 'null' by default instead 
 on `""`. Unless I state it explicitly with name="" ? o.O
Because string is simply `alias string = immutable(char)[]`, and default initializer for arrays is null.
Jun 13 2020