Jump to page: 1 2
Thread overview
Use of templates to avoid redudancy of code
Jun 03, 2008
Mael
Jun 03, 2008
Lutger
Jun 03, 2008
Chris Wright
Jun 03, 2008
Fawzi Mohamed
Jun 03, 2008
Fawzi Mohamed
Jun 03, 2008
Mael
Jun 04, 2008
Fawzi Mohamed
Jun 03, 2008
Mael
Jun 04, 2008
Fawzi Mohamed
Jun 04, 2008
Mael
Jun 04, 2008
Robert Fraser
Jun 04, 2008
janderson
Jun 04, 2008
janderson
June 03, 2008
Hello,

I'm writing an algorithm that has, say, too possible behaviour depending on a switch. Since there are many imbricated loops, and the behaviour change is inside the loop, testing for the flag is time-consuming

for( ....)
for( .... )
for( ... )
{
  if( flag ) action_1 ;
  else action_2 ;
}

is there a clean way to use templates to generate the duplicate of the code like

if( flag )
{
  for(...) .... action1 ;
}
else
{
  for(...) .... action2 ;
}


June 03, 2008
Mael wrote:

> Hello,
> 
> I'm writing an algorithm that has, say, too possible behaviour depending on a switch. Since there are many imbricated loops, and the behaviour change is inside the loop, testing for the flag is time-consuming
> 
> for( ....)
> for( .... )
> for( ... )
> {
>   if( flag ) action_1 ;
>   else action_2 ;
> }
> 
> is there a clean way to use templates to generate the duplicate of the code like
> 
> if( flag )
> {
>   for(...) .... action1 ;
> }
> else
> {
>   for(...) .... action2 ;
> }

If flag is a compile time constant, then you don't need no templates, just this:

static if (flag) action_1
else action_2

The if is evaluated only at compile time.

If behavior is changed at runtime, it would depend a little on the rest of the code, there are some different ways to implement if. For example as a helper function:

void func(bool flag)
{
    if (flag)
        helper!(true)();
    else
        helper!(false)();
}

void helper(bool flag)()
{
    for( ....)
    for( .... )
    for( ... )
    {
       static if( flag ) action_1 ;
       else action_2 ;
    }
}





June 03, 2008
Mael wrote:
> Hello,
> 
> I'm writing an algorithm that has, say, too possible behaviour depending on a switch. Since there are many imbricated loops, and the behaviour change is inside the loop, testing for the flag is time-consuming

You've profiled and you've determined that checking that bool is expensive. One option is checking it at compile time:

void action1(args);
void action2(args);
template action(bool isActionOne)
{
	static if (isActionOne)
		alias action1 action;
	else
		alias action2 action;
}

for (...)
	action!(flag);

// Or the same, but instead just hoping for inlining:
// global
const bool flag;
void action(args)
{
	static if (flag)
		action1(args);
	else
		action2(args);
}


If the flag changes at runtime...

Change your functions from:
void foo(args)
{
	for (i = 0; i < some_really_huge_number; i++)
		if (flag) action1(args); else action2(args);
}

void foo(alias fn)(args)
{
	for (i = 0; i < some_really_huge_number; i++)
		fn(args);
}

The vast majority of your methods would just pass on the alias template parameter. You'll still have to know about the flag and the functions wherever the flag might change, though.
June 03, 2008
On 2008-06-03 11:39:24 +0200, Mael <mael.primet@gmail.com> said:

> Hello,
> 
> I'm writing an algorithm that has, say, too possible behaviour depending on a switch. Since there are many imbricated loops, and the behaviour change is inside the loop, testing for the flag is time-consuming

I trust you really profiled the code to see this (never optimize before testing)

> for( ....)
> for( .... )
> for( ... )
> {
>   if( flag ) action_1 ;
>   else action_2 ;
> }
> 
> is there a clean way to use templates to generate the duplicate of the code like
> 
> if( flag )
> {
>   for(...) .... action1 ;
> }
> else
> {
>   for(...) .... action2 ;
> }

a simple compile time solution is to make the looping construct a template, and the action a template parameter (either alias or char[] to mixin if you need).

I used it extensively in my multidimensional array lib...


June 03, 2008
On 2008-06-03 15:19:33 +0200, Fawzi Mohamed <fmohamed@mac.com> said:

> On 2008-06-03 11:39:24 +0200, Mael <mael.primet@gmail.com> said:
> 
>> Hello,
>> 
>> I'm writing an algorithm that has, say, too possible behaviour depending on a switch. Since there are many imbricated loops, and the behaviour change is inside the loop, testing for the flag is time-consuming
> 
> I trust you really profiled the code to see this (never optimize before testing)

In case the issue is actually cleaning up the code, I would consider making the action a delegate that you pass in to your algorithm (and execute there).

June 03, 2008
> In case the issue is actually cleaning up the code, I would consider making the action a delegate that you pass in to your algorithm (and execute there).

This doesn't incur a penalty on the execution time ? Does it unfold the delegate as an inline function, or will there be calls to the delegate ?


June 03, 2008
> a simple compile time solution is to make the looping construct a template, and the action a template parameter (either alias or char[] to mixin if you need).
To what does the "alias" correspond ? A function acting on the code?

June 04, 2008
On 2008-06-03 20:17:16 +0200, Mael <mael.primet@gmail.com> said:

>> In case the issue is actually cleaning up the code, I would consider
>> making the action a delegate that you pass in to your algorithm (and
>> execute there).
> 
> This doesn't incur a penalty on the execution time ? Does it unfold the delegate as an inline function, or will there be calls to the delegate ?

yes this incurs a penalty if the delegate doesn't get inlined, and even if it does there might still be some small penalty.
So I said *if* you just need to clean up the code, then that is probably the best solution.

June 04, 2008
On 2008-06-03 20:20:16 +0200, Mael <mael.primet@gmail.com> said:

>> a simple compile time solution is to make the looping construct a
>> template, and the action a template parameter (either alias or char[]
>> to mixin if you need).
> To what does the "alias" correspond ? A function acting on the code?

this approach is like the delegate approach only that it is potentially faster.
An alias parameter to a template is a symbol that you pass to the template.
This symbol should be the delegate or function that executes the action.

void myAlgorithm(alias op)(args for the algorithm){
 for..
 for ..
   op();
}

the mixin is similar only that you pass a string and the string has access to all variables in the algorithm.
This is less safe, bur (form my experience with gdc) also potentially faster for very simple operations.

void myAlgorithm(char[] op_str)(args for the algorithm){
 for..
 for ..
   mixin(op_str);
}

op_str must be one (or more) complete statement (you need even the ";") and needs to be a string known at compile time.

Fawzi

June 04, 2008
okay thanks for the explanations,
the D language never specifies whether a function or template argument is inlined or not ?
It's left up to the compiler to choose what to do ?
« First   ‹ Prev
1 2