How to enable user to define "behavior mode" that a template function doIt(a,b)
will from another user-define variable/function op
AND optimize the if-else away?
Here is a working MCVE.
My VS solution has 2 projects. pj1 is my library. pj2 is user's project.
A_pj1.h
#pragma once
template<int T>class BoolT{public:
static bool op;
};
template<int T> bool BoolT<T>::op=true; //by default, true=+, false=-
template<int i> int doIt(int a,int b){
if(BoolT<i>::op){
return a+b;
}else{ return a-b;}
}
A_pj2_UserDefine.h
#pragma once
#include "A_pj1.h"
inline void A_pj2_UserDefine_Reg(){
BoolT<2>::op=false; //override default value;
}
A_pj2_main.cpp
#include "A_pj2_UserDefine.h"
#include <iostream>
int main(){
A_pj2_UserDefine_Reg();
int s1=doIt<1>(3,2); //= 5 (correct)
int s2=doIt<2>(3,2); //= 1 (correct)
std::cout << s1<<" "<<" "<<s2<<std::endl;
int asfasd=0;
}
(edit) Here is the disassembly (optimized version):-
int s2=doIt<2>(3,2);
std::cout << s1<<" "<<" "<<s2<<std::endl;
00B61620 mov ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (0B6B0A8h)]
int s1=doIt<1>(3,2); //:
00B61626 xor eax,eax
00B61628 cmp byte ptr [BoolT<1>::op (0B6E001h)],al
int s2=doIt<2>(3,2);
std::cout << s1<<" "<<" "<<s2<<std::endl;
00B6162E push offset std::endl<char,std::char_traits<char> > (0B61530h)
00B61633 push 1
int s1=doIt<1>(3,2); //:
00B61635 setne al
A_pj2_UserDefine_Reg();
00B61638 mov byte ptr [BoolT<2>::op (0B6E000h)],0
int s2=doIt<2>(3,2);
std::cout << s1<<" "<<" "<<s2<<std::endl;
00B6163F push offset string " " (0B6B220h)
00B61644 push offset string " " (0B6B220h)
int s1=doIt<1>(3,2); //:
00B61649 lea eax,[eax*4+1]
int s2=doIt<2>(3,2);
std::cout << s1<<" "<<" "<<s2<<std::endl;
00B61650 push eax
00B61651 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0B6B0B4h)]
00B61657 push eax
00B61658 call std::operator<<<std::char_traits<char> > (0B61310h)
00B6165D add esp,8
00B61660 push eax
00B61661 call std::operator<<<std::char_traits<char> > (0B61310h)
00B61666 add esp,8
00B61669 mov ecx,eax
00B6166B call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0B6B0B4h)]
00B61671 mov ecx,eax
00B61673 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0B6B0B8h)]
int asfasd=0;
}
00B61679 xor eax,eax
00B6167B ret
Problem
The doIt(a,b)
is called very often (>60000 per second).
I am curious if the if(BoolT<i>::op)
can be optimized out.
If-condition is not good for pipeline computation.
Here is my program behavior that may help :-
- Access-write to
BoolT<2>::op
always occur only at the beginning of program (e.g.A_pj2_UserDefine_Reg()
). - Function query
BoolT<2>::op
(both directly and indirectly) almost always occur only in the projectpj2
. - User can't edit pj1.
- In real case, besides
A_pj2_main.cpp
, there are a lot of.cpp
that callpj1
'sdoIt<>()
. Here is the include graph :-
My poor solution
B_pj1.h
#pragma once
template<int i> bool op(){return true;}
template<int i> int doIt(int a,int b){
if(op<i>()){
return a+b;
}else{ return a-b;}
// return a+b;
}
B_pj2_UserDefine.cpp
#include "B_pj1.h"
template<> bool op<2>(){return false;}
B_pj2_main.cpp
#include <iostream>
#include "B_pj1.h"
int main(){
int s1=doIt<1>(3,2); //:
int s2=doIt<2>(3,2);
std::cout << s1<<" "<<" "<<s2<<std::endl;
int asfasd=0;
}
This program is ill-formed. (Reference : Storing C++ template function definitions in a .CPP file)
Error LNK2005 "bool __cdecl op<2>(void)" (??$op@$01@@YA_NXZ) already defined in B_pj2_UserDefine.obj