1. 程式人生 > 其它 >C++ ---使用RTTI和模板的一個問題記錄

C++ ---使用RTTI和模板的一個問題記錄

背景:

提供一個寫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等級
};

通過引數的不同來呼叫不同的類的建構函式,達到可變引數的目的。