2013-10-08 65 views
1

是否有C++ 11或C++ 14,讓我們停止不必使用任何新設施:我可以區分一個和多個參數嗎?

TRACE0("one-string-no-args"); 

TRACE("formatting string with one-or-more args", arg1, arg2, etc); 

這些功能不得不通過名字來區分,因爲在我所知的情況下,重載不能將零附加參數的情況與一個或多個參數的情況區分開來。

這對於printf風格界面當然很重要,在那裏能夠知道沒有任何參數意味着您可以通過不嘗試將格式化字符串解釋爲格式化字符串來避免一類錯誤,而只是作爲最終輸出字符串。

+6

'無效跟蹤(串),''VS模板無效跟蹤(字符串,TS ...)'是編譯器完全區分。 – Xeo

+4

是的,** variadic模板**就是這樣做的。如果你不知道名字,那就是。 「安全」打印功能是可變參數模板的典型介紹性示例。 – DanielKO

+1

順便說一句我從來沒有用過它,但boost有一個非常酷的[命名函數參數模塊](http://www.boost.org/doc/libs/1_37_0/libs/parameter/doc/html/index.html)if你真的想把它帶到一個新的水平 – aaronman

回答

3

您可能只是不知道該功能的名稱:variadic templates

它的主要用途是從可變數量的參數中推導出可變數量的類型;你可以將它存儲在任何地方(如std::make_tuple()),或者只是打開參數來使用它們。

這是一個基本用法:

void print() {} 

template<class Head, class... Tail> 
void print(Head h, Tail... t) 
{ 
    cout << h << endl; 
    print(t...); 
} 

int main() 
{ 
    print(3, "hello", 4.5); 
} 

看到它在這裏的行動:http://ideone.com/VA7YGK

正如你可以看到它看起來像函數式編程(!因爲它),在那裏你對陣的規則將參數列表拆分成一個頭部和一個尾部,然後用少一個元素調用自己。

又如,從最近的問題,其中,I遞歸地定義的數據結構(短和足夠簡單是可讀的):Multikey map using variadic templates

std::thread構造函數被另一個例子,它採用可變數目的參數,得到一旦它開始在產生的線程中運行,它們就是函數;幾乎所有與C++ 11交互的新功能(例如std::function)都使用可變參數模板,以便它們可以接受任意類型的任意數量的參數。 std::tuple,std::make_tuple()std::tie()也可以使用它。

在網上搜索,你會發現很多更先進的用法。要特別注意擴展參數的規則和完善的轉發。

0

對於TRACE宏(通常包含在Microsoft的調試宏中),no,該語言不會有用於處理預處理宏的「新」方法(它實際上與以前相同)。

對於一般功能,可變參數函數一直都受支持(例如printf)。

0

這對某些人來說可能看起來很愚蠢 - 但我有一噸C風格的printf代碼需要維護。

我們可以使用boost的格式化庫來重建它,也許我們會在這些日子之後進行重建。然而,與此同時,能夠區分一個論點或一個+一個或多個論點是向前邁出的一大步。

https://stackoverflow.com/users/365496/bames53指出有可能這樣做,它似乎工作(在代碼膨脹,並與警告,這仍然是printf土地與所有的陷阱一些可能的代價)。

下面是一個簡單的例子,做它的工作在MFC/C++:

bool Write(const wchar_t * pszText); 
template <typename T> bool Write(const wchar_t * pszFormat, T, ...); 

寫,不需要(也不應該)調用vwsprintf等同,而寫<>並以構建輸出這樣做字符串在傳遞給Write之前。

非常優雅。消除了只提供第二個接口的問題(如果你的一個字符串碰巧有一個意外的printf格式說明符),或者強制客戶端指定Write()與WriteFormat()或者類似地執行調用Write()之前在本地創建字符串。

這裏寫<>在寫來定義:

template <typename T> bool SimpleTextFile::Write(const wchar_t * pszFormat, T, ...) 
{ 
    va_list arglist; 
    va_start(arglist, pszFormat); 
    CStringW buffer; 
    buffer.FormatV(pszFormat, arglist); 
    va_end(arglist); 
    return Write(buffer); 
} 
相關問題