2

This code fails at the second unittest at the getA!B() call. The error is: "need 'this' for 'value' of type 'string'"

The question is. How do I get getA to always return a A, whether the UDA is a type or an opCall?

    static A opCall(T...)(T args) {
        A ret;
        ret.value = args[0];
        return ret;
    }

    string value;
}

@A struct B {
}

@A("hello") struct C {
}

A getA(T)() {
    foreach(it; __traits(getAttributes, T)) {
        if(is(typeof(it) == A)) {
            A ret;
            ret.value = it.value;
            return ret;
        }
    }

    assert(false);
}

unittest {
    A a = getA!C();
    assert(a.value == "hello");
}

unittest {
    A a = getA!B();
    assert(a.value == "");
}
burner
  • 323
  • 2
  • 10

1 Answers1

2

As you know, traits are evaluated at compile-time. So any introspection on values obtained via __traits must be done statically. Luckily D has the "static if condition" for this.

If you change

if(is(typeof(it) == A)) {

to

static if (is(typeof(it) == A)) {

you should not have problems compiling the code as is(typeof(it) == A can be evaluated at compile-time.

DejanLekic
  • 18,787
  • 4
  • 46
  • 77
  • What bugs me is that the foreach is not static but actually is. – burner Jun 17 '14 at 11:12
  • Good point. There have been suggestions on the D newsgroups to have `static foreach`. In this case, foreach iterates over tuples known at compile-time, so D does not complain. :) – DejanLekic Jun 17 '14 at 11:32
  • I followed that thread a bit. It is always funny and scary what the D frontend accepts and what not ;-) – burner Jun 17 '14 at 12:07