dmlc throws "unknown identifier" without using #if

96 views Asked by At

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

There are 1 answers

2
Erik Carstensen On BEST ANSWER

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.