View mode: basic / threaded / horizontal-split · Log in · Help
July 29, 2008
Recursive template problem
Hello,

I want to make a template that evaluates to the summed absolute values 
of the elements of an array. In other words, I want something like this:

    real[3] foo;
    real sum = absSum!(foo);

to expand (at compile time) to

    real[3] foo;
    real sum = abs(foo[0]) + abs(foo[1]) + abs(foo[2]);

So, I wrote the following templates:

    private template absSum(real[N] V, ulong N) {
        real absSum = absSum!(V, N-1) + abs(V[N-1]);
    }
    private template absSum(real[N] V, ulong M, ulong N) {
        real absSum = absSum!(M-1, V) + abs(V[M-1]);
    }
    private template absSum(real[N] V, ulong M : 1, ulong N) {
        real absSum = abs(V[0]);
    }

but on compilation I get (for each template!) the error messages

  variable N forward referenced
  Error: Integer constant expression expected instead of N
  Error: Integer constant expression expected instead of N
  Error: Integer constant expression expected instead of N
  variable N forward referenced
  Error: Integer constant expression expected instead of N
  Error: Integer constant expression expected instead of cast(ulong)N
  Error: Integer constant expression expected instead of cast(ulong)N
  Error: arithmetic/string type expected for value-parameter, not real[N]

I haven't a clue why I am getting these messages. Any tips?

Thanks,

-Lars
July 29, 2008
Re: Recursive template problem
Reply to Lars,

> Hello,
> 
> I want to make a template that evaluates to the summed absolute values
> of the elements of an array. In other words, I want something like
> this:
> 
> real[3] foo;
> real sum = absSum!(foo);
> to expand (at compile time) to
> 
> real[3] foo;
> real sum = abs(foo[0]) + abs(foo[1]) + abs(foo[2]);
> So, I wrote the following templates:
> 
> private template absSum(real[N] V, ulong N) {
> real absSum = absSum!(V, N-1) + abs(V[N-1]);
> }

right off that should be "const real ..."

> private template absSum(real[N] V, ulong M, ulong N) {
> real absSum = absSum!(M-1, V) + abs(V[M-1]);
> }
> private template absSum(real[N] V, ulong M : 1, ulong N) {
> real absSum = abs(V[0]);
> }
> but on compilation I get (for each template!) the error messages
> 
> variable N forward referenced
> Error: Integer constant expression expected instead of N
> Error: Integer constant expression expected instead of N
> Error: Integer constant expression expected instead of N
> variable N forward referenced
> Error: Integer constant expression expected instead of N
> Error: Integer constant expression expected instead of cast(ulong)N
> Error: Integer constant expression expected instead of cast(ulong)N
> Error: arithmetic/string type expected for value-parameter, not
> real[N]

I'm not shure arrays of real are allowd for template args


2 options:

CTFE:

real AbsSum(real[] args){
real ret=0;
foreach(real r;args)
 if(r > 0) ret += r;
 else if(r < 0) ret -= r;
 //else 0 or nan: do nothing

return ret;
}


tuples:

template AbsSum(T...)
{
 static if(T.length == 0)
   const real AbsSum = 0;
 else
 {
   static if(T[0] > 0
     const real AbsSum = AbsSum(T[1..$]) + T[0];
   else static if(T[0] < 0
     const real AbsSum = AbsSum(T[1..$]) - T[0];
   else
     const real AbsSum = AbsSum(T[1..$]);
 }
}
Top | Discussion index | About this forum | D home