Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 03, 2008 Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mael | 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mael | 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mael | 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Fawzi Mohamed | 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Fawzi Mohamed | > 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Fawzi Mohamed | > 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mael | 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mael | 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 Re: Use of templates to avoid redudancy of code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Fawzi Mohamed | 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 ? |
Copyright © 1999-2021 by the D Language Foundation