背景:
提供一个写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等级 };
通过参数的不同来调用不同的类的构造函数,达到可变参数的目的。