Как разрешить пользователю определять «режим поведения», который шаблонная функция doIt(a,b)
будет извлекать из другой определяемой пользователем переменной / функции op
И , оптимизировать , если иное удалено?
Вот рабочий MCVE.
Мое решение VS имеет 2 проекта. pj1 - моя библиотека. pj2 - проект пользователя.
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;
}
(правка) Вот разборка (оптимизированная версия): -
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
Проблема
doIt(a,b)
вызывается очень часто (> 60000 в секунду).
Мне любопытно, можно ли оптимизировать if(BoolT<i>::op)
.
Условие if не подходит для вычисления конвейера.
Вот поведение моей программы, которое может помочь: -
- Доступ-запись в
BoolT<2>::op
всегда происходит только в начале программы (например, A_pj2_UserDefine_Reg()
).
- Функция запроса
BoolT<2>::op
(как прямо, так и косвенно) почти всегда происходит только в проекте pj2
.
- Пользователь не может редактировать pj1 .
- В реальном случае, кроме
A_pj2_main.cpp
, существует множество .cpp
, которые вызывают pj1
'doIt<>()
. Вот график включения: -
Мое плохое решение
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;
}
Эта программа некорректна. (Ссылка: Хранение определений функций шаблона C ++ в файле .CPP )
Ошибка LNK2005 "bool __cdecl op <2> (void)" (?? $ op @ $ 01 @@ YA_NXZ) уже
определено в B_pj2_UserDefine.obj