Error using templates: "cannot use template to add field to aggregate '<class>'"

Chris Wright via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Jan 25 08:12:58 PST 2016


On Mon, 25 Jan 2016 14:51:21 +0000, pineapple wrote:

> I'm getting several of these since I'm trying to do the same thing in a
> few places. Here's a complete error:
> 
>      path\to\file.d(55): Error: variable
> units.unitvalue.opmethod!("sum(in unitvalue value)",
> "add(value)").methodtemplate cannot use template to add field to
> aggregate 'unitvalue'
>      path\to\file.d(127): Error: template instance
> units.unitvalue.opmethod!("sum(in unitvalue value)", "add(value)") error
> instantiating

That looks like the right error.

>      template opmethod(string methoddef, string methodcall){
>          const char[] methodtemplate =

Change it from 'const' to 'enum' and Bob's your uncle.

Short explanation:

'enum' refers to compile-time constants. 'const' is a promise that you 
will not mutate a variable through that reference. Anything that's not a 
compile-time constant in an aggregate body requires storage space within 
that aggregate, resulting in an unbounded set of fields.

Exhaustive explanation:

'const' indicates that you cannot mutate the data through this reference 
(but it can be mutated elsewhere). It's not referring to compile-time 
constants. For instance, it's entirely legal (and reasonable) to write:

class OptParse {
  const(string[]) args;
  this(const(string[]) args) {
    this.args = args;
  }
}
void main(string[] args) {
  new OptParse(args);
}

Which indicates that OptParse is not going to modify the args array. 
You're grabbing command-line arguments and passing them in, which means 
they're not a compile-time constant. So the OptParse class has to include 
a storage slot reserved for the 'args' variable.

In your case, 'methodtemplate' isn't declared as a compile-time constant. 
It has an initializer that's a compile-time constant, but you aren't 
guaranteeing that the value isn't going to be changed.

That would be fine, but it's inside a template. Templates can be 
instantiated a potentially unlimited number of times. So the compiler 
comes across this type, tries to compute its size and fields -- but it 
doesn't know for certain at this point how many times you're 
instantiating the template. So it can't list out all the fields.

It would be possible if D compiled a whole program at once. This would 
prevent you from publishing closed-source libraries, however, and 
increase compilation times.


More information about the Digitalmars-d-learn mailing list