2012-12-06 257 views
2

簡短版本:如何將變量參數函數中的...代表的內容傳遞給另一個函數,而無需先將其解析爲va_list如何將變量參數傳遞給另一個函數?

龍版本:

下面是一類礦井的兩個功能。我想提請你注意,每個功能的前四行是相同的。而且我在這門課中有六個與前四行相同的其他功能。

void cyclOps::Logger::warn(char* szFile, char* szFunction, int iLine, char* szFormat, ...) { 
    va_list vaArguments; 
    va_start(vaArguments, szFormat); 
    char szOutput[10000]; 
    _vsnprintf_s(szOutput, CYCLOPSSIZEOF(szOutput), _TRUNCATE, szFormat, vaArguments); 
    this->log("WARNING: %s [%s - %s(%d)]", szOutput, szFile, szFunction, iLine); 
} 

void cyclOps::Logger::info(char* szFormat, ...) { 
    va_list vaArguments; 
    va_start(vaArguments, szFormat); 
    char szOutput[10000]; 
    _vsnprintf_s(szOutput, CYCLOPSSIZEOF(szOutput), _TRUNCATE, szFormat, vaArguments); 
    this->log("INFO: %s", szOutput); 
} 

我願把這四個相同的線稱爲summarizeVariableArguments()一個單一的功能,並調用它像這樣...

void cyclOps::Logger::info(char* szFormat, ...) { 
     std::string strOutput = this->summarizeVariableArguments(/* TBD */); 
    this->log("INFO: %s", strOutput.c_str()); 
} 

...其中的strOutput的內容是相同的作爲前兩個函數中szOutput的內容。但是,如何將...參數傳遞給另一個函數?

+0

我不認爲你可以這樣做。你必須首先解析並重新包裝列表。 – Mike

+0

你不能。對於日誌記錄,我建議你使用輸出流範例,使用'<<'運算符將輸出鏈接在一起。當然,在C程序中是不可能的,只能用C++。 –

+0

你的內部函數應該都是'va_list'。只有外層應該使用'...',然後調用'va_list'版本,因爲你不能將一個'...'設置爲另一個。這也是爲什麼像'vfprintf','vsprintf'等函數存在的原因。 – melpomene

回答

4

你不能這麼做(或者在編譯時,可怕的C++ 2011可變參數模板技巧)。

如果要在運行時調用可變參數函數,則可能需要使用libffi

詳細信息是操作系統,編譯器,處理器和ABI特定的。 (但libffi正試圖抽象它們)。

+1

我不知道我會打電話variadic模板「可愛」... :) – Xymostech

+0

+1。即使Dropbox傢伙在代碼中犯了這個錯誤。韋爾普。 – 2012-12-06 17:17:12

+0

更正'可愛' - >'可怕' –

2

你讓接受va_list做的工作,像這樣的另一個功能:

void cyclOps::Logger::vLog(const char* format, va_list args) 
{ 
    std::string logMessage = vFormat<10000>(format, args); 
    // Do what you want with logMessage 
} 

template <size_t BufferSize> 
std::string cyclOps::Logger::vFormat(const char* format, va_list args) 
{ 
    char buffer[BufferSize]; 
    vsprintf(buffer, format, args); 
    return std::string(buffer); 
} 

我已經測試這對MSVC和GCC爲我的項目。我只能說這對我很有用。

這裏是working example。這個解決方案適用於C++ 03,我相信應該可以與C++ 11一起工作。

+1

儘管在其他答案的末日審判者,這種方法已經有效C四十年。 –

+0

我不知道爲什麼@Basile說沒有便攜式解決方案。但以我有限的經驗,這應該是可移植的,就像你說的。但也許我錯過了一些東西,因此我的短語'它適用於我'。 –

+0

只是給你一些備份... –

4

That's what perfect forwarding is all about + variadic模板。

template<typename ...Args> 
void cyclOps::Logger::info(char* szFormat, Args &&...args) { 
    std::string strOutput = this->summarizeVariableArguments(std::forward<Args>(args)...); 
    this->log("INFO: %s", strOutput.c_str()); 
} 
相關問題