2

Why do I get an unknown identifier error for the fail_test1 template and not in pass_test1?

template pass_test1 {
    param len = 10;

    #if (true) {
    saved int8 data[len];
    }
}

group pass is pass_test1;

template fail_test1 {
    param len = 10;

    saved int8 data[len];
}

group fail is fail_test1;

1 Answers1

2

In short: in pass_test1 the saved declaration is not part of the template type, whereas in fail_test1 it is. And the error message comes from DMLC trying to parse the type of data as a member of the template type.

This happens because saved declarations are normally added to the template type: If you silence the error by s/len/10/, then you can write a run-time reference to it, as local fail_test1 x = cast(fail, fail_test1), and then you can access x.data. However, this does not work for pass_test1: you can write local pass_test1 y = cast(pass, pass_test1) but then you cannot access y.data. Conditional parts of a template cannot be part of the template's type, because there is no reasonable way for the run-time reference to handle the case when the #if condition of the referenced object is false.

A funny consequence is that your #if (true) { saved data[len]; } construct is in fact the recommended idiom for parameterized array members of templates. It looks a bit odd, but it happens to do exactly what you want, and it's uncommon enough that we probably won't invent a special syntax for it.

If you want to access the data member from the template type, then you will need to leverage a shared method with a non-shared implementation:

template pass {
  param len default 10;
  #if (true) { saved int8 data[len]; }
  shared method get_data() -> (int8*);
  method get_data() -> (int8*) {
    return data;
  }
}

Here, get_data() is a member of the template type which allows access to the array, while still keeping the array length configurable.

Love Waern
  • 105
  • 2
Erik Carstensen
  • 634
  • 4
  • 14
  • 1
    Thanks. Is casting necessary to get the members of a template type? Would pass.data work without the need for casting? – Anthony Moore Jan 05 '23 at 16:59
  • 2
    An object reference expression is currently not a value in itself; one object can implement many templates and a value must have an unambiguous type. The cast is currently needed to disambiguate the template type. We have some ideas to make the cast optional where the desired template type can be inferred, such as variable initializers or method arguments. – Erik Carstensen Jan 09 '23 at 13:28