Recursive template expansion

Robert Jacques sandford at jhu.edu
Mon Mar 1 08:16:19 PST 2010


On Mon, 01 Mar 2010 04:16:41 -0500, Norbert Nemec  
<Norbert at nemec-online.de> wrote:
> Hi there,
>
> trying out a few ideas on expression templates, I stumbled over the  
> following problem, for which I cannot find a solution. The code below  
> demonstrates what I try to do:
>
> I need to construct a nested template type at compile time. Any  
> expression should correspond to an equivalent nested tree of templates  
> which can then be unraveled at compile time.
>
> For some reason, the D compiler complains about a "recursive template  
> expansion" as soon as I use ((a+b)+c). My guess is that this is supposed  
> to protect against infinite recursions at compile time. In this case,  
> however, there is actually no risk of that. Nested types are only needed  
> at the depth of nested expressions that actually occur.
>
> Is there any fundamental error in my thinking? Some simple  
> misunderstanding? Some slightly different syntax to be used? Or is it  
> simply an unnessessary restriction in the compiler that could easily be  
> removed?
>
> Apart from all that, I want to point out that the error message does not  
> even give a line number in the code. If any such error occurs within a  
> larger piece of software, identifying the problem would be a nightmare!
>
> Greetings,
> Norbert
>
>
> ---------------
> import std.stdio;
>
> struct sum(A,B) {
>      A a;
>      B b;
>
>      auto opAdd(T)(T a) { return .sum!(sum,T)(this,a); }
> }
>
>
> struct base {
>      auto opAdd(T)(T a) { return .sum!(base,T)(this,a); }
> }
>
> void main() {
>      base a,b,c;
>
>      // first a few working examples
>      writeln(typeid(a));       // base
>      writeln(typeid(a+b));     // sum!(base,base).sum
>      writeln(typeid(a+(b+c))); // sum!(base,sum!(base,base)).sum
>
>      sum!(sum!(base,base),base) d;
>      writeln(typeid(d));       // sum!(sum!(base,base),base).sum
>
>      // the following produces
>      //   Error: recursive template expansion for
>      //   template argument sum!(base,base)
>      writeln(typeid((a+b)+c)); // sum!(sum!(base,base),base).sum
> }
>
> ---------------

Well, first and foremost you should file the missing line number bug in  
bugzilla. As for the RTE itself, logically it shouldn't happen with this,  
but here are some work arounds.
1) Alter the type signature with a dummy var
struct sum(A,B,bool FLAG = false) {
      A a;
      B b;
      auto opAdd(T)(T a) { return sum!(sum!(A,B,!FLAG),T)(this,a); }
}
2) use a typedef
struct sum(A,B) {
      A a;
      B b;
private typedef sum __sum;
      auto opAdd(T)(T a) { return sum!(__sum,T)(this,a); }
}

3) You could also switch to using a generic expression template. i.e.  
op(string expression, string nextVar, T...) {}



More information about the Digitalmars-d mailing list