## digitalmars.D - Recursive template problem

• Lars Kyllingstad (31/31) Jul 29 2008 Hello,
• BCS (28/63) Jul 29 2008 I'm not shure arrays of real are allowd for template args
• maelp (12/12) Jul 30 2008 I think what he looks for is not the actual result since his array of re...
• Max Samukha (24/36) Jul 30 2008 One of a few ways to do that:
• Lars Kyllingstad (10/11) Jul 30 2008 That's right. I am using D for numerical computations, so fast-executing...
• BCS (10/34) Jul 30 2008 First take a look at the code here, it might give you some ideas:
```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
```
Jul 29 2008
```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..\$]);
}
}
```
Jul 29 2008
maelp <mael.primet gmail.com> writes:
```I think what he looks for is not the actual result since his array of reals
isn't const (not known at compile time), and he simply wants the actual *code*
to be generated at compile time, so none of your solution will work. I've had
similar problems of recursive template construction, so since there are several
posts, maybe we'll have some answers.

My problem was to construct a struct having k (known at compile time) elements
named (for instance)
v1 ... vk,

ie. something like

MyStruct!(5)

=>

struct
{
int v1, v2, v3, v4, v5 ;
}

someone could help me with this? Or is it possible to do this?

```
Jul 30 2008
Max Samukha <samukha voliacable.com.removethis> writes:
```On Wed, 30 Jul 2008 04:39:42 -0400, maelp <mael.primet gmail.com>
wrote:

I think what he looks for is not the actual result since his array of reals
isn't const (not known at compile time), and he simply wants the actual *code*
to be generated at compile time, so none of your solution will work. I've had
similar problems of recursive template construction, so since there are several
posts, maybe we'll have some answers.

My problem was to construct a struct having k (known at compile time) elements
named (for instance)
v1 ... vk,

ie. something like

MyStruct!(5)

=>

struct
{
int v1, v2, v3, v4, v5 ;
}

someone could help me with this? Or is it possible to do this?

One of a few ways to do that:

import std.stdio;
import std.metastrings;

template Fields(uint n)
{
static if (n)
{
mixin ("int v" ~ ToString!(n) ~ ";");
mixin Fields!(n - 1);
}
}

struct S(uint n)
{
mixin Fields!(n);
}

void main()
{
S!(5) s;
s.v1 = 1;
s.v2 = 2;
s.v5 = 3;
}
```
Jul 30 2008
```maelp wrote:
I think what he looks for is not the actual result since his array of reals
isn't const (not known at compile time), and he simply wants the actual *code*
to be generated at compile time, so none of your solution will work. I've had
similar problems of recursive template construction, so since there are several
posts, maybe we'll have some answers.

That's right. I am using D for numerical computations, so fast-executing
code is essential. Therefore, I want to use static arrays whenever
possible, and instead of having to write

foreach (real r; v) sum += r;

or similar, i would like expressions such as

sum = v[0] + v[1] + ...

to be created at compile time for arrays of any given length. I was
kinda hoping templates could provide a solution...

-Lars
```
Jul 30 2008
```Reply to Lars,

maelp wrote:

I think what he looks for is not the actual result since his array of
reals isn't const (not known at compile time), and he simply wants
the actual *code* to be generated at compile time, so none of your
solution will work. I've had similar problems of recursive template
construction, so since there are several posts, maybe we'll have some

That's right. I am using D for numerical computations, so
fast-executing code is essential. Therefore, I want to use static
arrays whenever possible, and instead of having to write

foreach (real r; v) sum += r;

or similar, i would like expressions such as

sum = v[0] + v[1] + ...

to be created at compile time for arrays of any given length. I was
kinda hoping templates could provide a solution...

-Lars

First take a look at the code here, it might give you some ideas:
http://www.dsource.org/projects/scrapple/browser/trunk/bignum/bignum.d

somewhere in there is a hunk of code that generate a tuple like T!(1, 2,
4, 5, ...)
using a foreach over that will let you get compile time enumeration.

Another point to be made is that if you are reading more than just a few
numbers you may actually be ahead to use the foreach as its code will be
much shorter (lower memory usage = better cache usage). As a first guess,
if the unrolled code is more than a memory page long, loop.
```
Jul 30 2008