C++ ---使用RTTI和模板的一個問題記錄
阿新 • • 發佈:2021-06-10
背景:
提供一個寫log的介面,引數支援int,float,string,QString,char*等幾個型別的輸入。
想法:
介面為模板函式,並通過C++提供的type_info類獲取輸入引數的型別,在介面內部統一將引數轉換為string,然後寫入log。
錯誤程式碼:
//支援string QString 整型(會轉為int輸出)和浮點型(浮點會轉為double輸出) template<class T> int mDLLLogCatfunc(T log, int level = 0) { if ( level < logLevel ) {return VIS_Result_PASS; } ///不用判斷型別:如果有不支援的型別,編譯時會檢測到,並報錯。 // QString logType = typeid (log).name(); // if ( logType.contains("short") || logType.contains("int") || logType.contains("float") || logType.contains("double") || logType.contains("int64") || logType.contains("basic_string")// || logType.contains("QString") || logType.contains("char const *")) // { // ShiftLog happy(log); // mMutexLog.lock(); // stringLog.push(happy.strLog); // mMutexLog.unlock(); // qDebug()<< QString::fromStdString(happy.strLog);// return VIS_Result_PASS; // } QString logType = typeid (log).name(); QString happy; if ( logType.contains("short") || logType.contains("int") || logType.contains("float") || logType.contains("double") || logType.contains("int64") ) { happy = QString("%1").arg(log); } else if( logType.contains("basic_string") || logType.contains("char const *")) { happy = QString::fromStdString(log); } else if (logType.contains("QString") ) { happy = log; } mMutexLog.lock(); stringLog.push(happy); mMutexLog.unlock(); return VIS_Result_PASS; }
就按照想法把程式碼翻譯出來,結果編譯時報錯。
邏輯上沒問題。但是編譯時是會把if{...} else if{...} else if{...},都編譯。模板函式會在例項化的時候進行編譯,比如 mDLLLogCatfunc(88); 這個時候 if 沒問題,但是後面兩個 else if 就會報錯,因為QString::fromStdString引數不支援,happy = log也是不支援 int 到QString的過載。這裡的if{...} else if{...} else if{...}並不是#if #elif。
優化:
//如果直接在模板函式中實現,會報錯:編譯會將全部程式碼都編譯,所以會有某些型別無法轉換 class ShiftLog { public: ShiftLog(short &log); ShiftLog(int &log); ShiftLog(float &log); ShiftLog(double &log); ShiftLog(long long &log); ShiftLog(QString &log); ShiftLog(string &log); ShiftLog(const char* &log); string strLog; }; class ViFunc { public: static ViFunc &GetViFunc() { static ViFunc viFunc("imgSys.dll"); return viFunc; } int VI_DLLAlgorithm(string AlgorithmName, bool* wait, vector<cv::Mat> inMat, vector<string> inString, vector<int> inNum, vector<cv::Rect> inRect, pstInputVar inVariable, vector<cv::Mat> *outMat, vector<string> *outstring, vector<int> *outInt, vector<cv::Rect> *outRect);//呼叫AlgorithmName函式 //支援string QString 整型(會轉為int輸出)和浮點型(浮點會轉為double輸出) template<class T> int mDLLLogCatfunc(T log, int level = 0) { if ( level < logLevel ) { return VIS_Result_PASS; } ///不用判斷型別:如果有不支援的型別,編譯時會檢測到,並報錯。 // QString logType = typeid (log).name(); // if ( logType.contains("short") || logType.contains("int") || logType.contains("float") || logType.contains("double") || logType.contains("int64") || logType.contains("basic_string") // || logType.contains("QString") || logType.contains("char const *")) // { // ShiftLog happy(log); // mMutexLog.lock(); // stringLog.push(happy.strLog); // mMutexLog.unlock(); // qDebug()<< QString::fromStdString(happy.strLog); // return VIS_Result_PASS; // } ShiftLog happy(log); mMutexLog.lock(); stringLog.push(happy.strLog); mMutexLog.unlock(); return VIS_Result_PASS; } private: ViFunc(const char* dllPath); ViFunc(const ViFunc &v); ViFunc operator =(const ViFunc &v); virtual ~ViFunc(); //調演算法 HINSTANCE imgSysHandler;//載入ImgSys SysAlg mSysAlgorithm[MAX_FUNC_NUM]; mutex mMutexFunc;//呼叫函式時,加鎖 //寫Log queue<string>stringLog; mutex mMutexLog;//寫log加鎖 int logLevel;//寫log等級 };
通過引數的不同來呼叫不同的類的建構函式,達到可變引數的目的。