On Mon, 01 Mar 2010 04:16:41 -0500, Norbert Nemec <[email protected]> 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...) {}

Reply via email to