2017-08-11 95 views
4

我有我的應用程序的不同部分調用記錄器功能來記錄詳細信息。C++連接不同類型爲函數的字符串

Logger類

std::string filename = "blahblah"; // variable to store the location of the properties file 
log4cpp::PropertyConfigurator::configure(filename); 

void Logger::logging(const std::string& msg) 
{ 
    Log4cpp::Category& myLogger = log4cpp::Category::getRoot(); 

    myLogger.log(log4cpp::Priority::INFO, msg);//only takes in string as input 
} 

調用類

Logger logMe; 

int a = 5; 
double b = 6; 

logMe.logging("log this msg" + a + "," + b); 

我意識到,上面給我的錯誤,因爲ab是不同類型的。解決這個問題的方法之一是使用std::to_string

logMe.logging("log this msg" + std::to_string(a) + "," + std::to_string(b)); 

不過,我有上百個電話到日誌功能,這將是耗時每個調用編輯到std::to_string。是否有更簡單的方法可以做到這一點?

呵呵並且爲了澄清,代碼之前的工作方式是通過定義#define函數。

#Define logging(FLAG, X)\ 
do {\ 
    ... 
    clog << x; \ 
}while(0) 

logging(LogFlag::Warning, "log this msg" << a << "," << b << endl); 

但我現在正在重寫部分代碼以符合靜態測試。

在此先感謝。

+2

應該以標準庫爲例 - 實現'operator <<'。 – LogicStuff

回答

4

您可以添加的logging,需要一個參數組,並加入它轉換成字符串超載,使用std::stringstream

在C++ 17中,我們可以用一個fold expression,例如

template <typename Args ...> 
void Logger::logging(Args ... args) 
{ 
    std::stringstream ss; 
    (ss << ... << args); 

    Log4cpp::Category& myLogger = log4cpp::Category::getRoot(); 

    myLogger.log(log4cpp::Priority::INFO, ss.str()); 
} 

在C++ 11或14中,我們必須slightly more tricky

template <typename ... Args > 
void Logger::logging(Args ... args) 
{ 
    std::stringstream ss; 
    std::initializer_list<int> unused{ (ss << args, 0)... }; 

    Log4cpp::Category& myLogger = log4cpp::Category::getRoot(); 

    myLogger.log(log4cpp::Priority::INFO, ss.str()); 
} 

然後調用或者作爲例如

logMe.logging("log this msg", a, ",", b); 
+0

我試過使用這種方法,但我得到「無效的操作數類型'const unsigned int'到二進制'operator <<'。該方法只適用於int,因爲std :: initializer_list ? –

+0

@TonyTony你怎麼稱呼它?它應該是'logMe.logging(「log this msg」,a,「,」,b);' – Caleth

3

這很容易使用stringstream。您可以使用str()將其轉換爲std::string

#include <sstream> 
... 
int a = 5; 
double b = 6; 

std::stringstream ss; 
ss << "log this msg" << a << b; 
std::cout << ss.str() << std::endl; 
logMe.logging(ss.str()); 
+0

我知道我可以使用stringstream,但是我仍然必須將std :: stringstream代碼添加到調用logMe.logging的每一行。所以如果我有500個電話,我必須添加std :: stringstream代碼500次。因此,我問是否有更簡單的方法。但謝謝你的回答! –

+0

@TonyTony我不確定除了覆蓋操作員之外是否有更簡潔的方法。但是,我認爲需要更改很多代碼?即無論您在哪裏進行日誌調用。 – iyop45

+0

對運營商來說,似乎是迄今爲止最好的解決方案。但是,如果說我想添加另一個參數來指定日誌標誌,問題就會出現。 (例如,logMe。日誌記錄(Flag :: Warning,「log this msg」); –

4

我建議增加一個operator<<()到類

class Logger 
{ 
    public: 

      Logger &operator<<(const std::string &s) 
      { 
       logging(s) 
       return *this; 
      }; 

      Logger &operator<<(const char *s) 
      { 
       return operator<<(std::string(s)); 
      } 


      template <class T> 
       Logger &operator<<(const T &v) 
      { 
       std::ostringstream s; 
       s << v; 
       return operator<<(logging(ss.str())); 
      }; 

     // other stuff you have in your class, including the logging() function 
}; 

// to use 

logMe << "log this msg" << a << b; 

不太如你所描述使用此相同的語法,但它的作品更普遍。