I have to use variable v
in 5-10 locations in a function.
From profiling, v
is (relatively) very expensive to initialize.
How to initialize v
only when needed?
It is unfortunate that it is a engine-code.
Adding some if-else will easily become bottleneck.
#include <iostream>
#include <cstdlib>
#include <utility>
template<int flag1,int flag2,int flag3> int expensiveFuncion(){
/// Some expensive algorithm that has no side effect.
/// Used only to initialize 'v' when needed.
return 0;
}
template<int flag1,int flag2,int flag3> void f(int& a){
int v=expensiveFuncion<flag1,flag2,flag3>();
if constexpr(flag1==0){ /// some complex condition on flags
if constexpr(flag3==2){/// some complex condition on flags
/// some complex algorithm that used 'v'
}else if constexpr(flag2%2==0){/// some complex condition on flags
if constexpr(flag3==2){/// some complex condition on flags
/// another different complex algorithm that used 'v'
}else{
/// another different complex algorithm that NOT used 'v'
}
}
///... a lot of branches with different condition,
/// only some branches use 'v'
}
}
int main(){
int k=0;
f<0,2,4>(k);
}
My poor solution
Adding a flag near v
like bool is_v_initialized=false
.
When used ::-
if(!is_v_initialized){
v=expensiveFuncion<flag1,flag2,flag3>();
is_v_initialized = true;
}
Result :: if(!is_v_initialized)
becomes a new bottleneck.
My poor solution 2
I insert initialization code to the top of algorithm, and query only when needed beforehand.
template<int flag1,int flag2,int flag3> void f(int& a){
int v=-1234;
///vvv duplicated condition
if constexpr(flag1==0){
if constexpr(flag3==2){
v=expensiveFuncion<flag1,flag2,flag3>();
}else if constexpr(flag2%2==0){
if constexpr(flag3==2){
v=expensiveFuncion<flag1,flag2,flag3>();
}else{
}
}
///...
}
///^^^ duplicated condition
/// real algorithm is below
if constexpr(flag1==0){ /// some complex condition on flags
if constexpr(flag3==2){/// some complex condition on flags
....
}
Result:: This is very migraine-induce to maintain, but works and super fast.