2011-07-06 24 views
10

我知道答案常問How do I specify a pointer to an overloaded function?:要麼與轉讓或與演員陣容,和所有其他的C++教程轉換爲大寫像這樣的字符串(給予或採取static_cast):如何在算法中使用帶默認參數的重載函數?

transform(in.begin(), in.end(), back_inserter(out), (int(*)(int)) std::toupper); 

或者這樣:

int (*fp)(int) = std::toupper; 
transform(in.begin(), in.end(), back_inserter(out), fp); 

整齊地選擇<cctype>過載的std::toupper

但是這引出了一個問題:我怎樣才能以類似的方式選擇<locale>過載?

char (*fp2)(char, const std::locale&) = std::toupper; 
transform(in.begin(), in.end(), back_inserter(out), fp2); 
// error: too few arguments to function 

或者,更實際,考慮有人試圖用C++ 11 std::stoi在算法爲字符串的向量轉換爲整數的向量:stoi有兩個重載(string/wstring),每次服用兩個額外的默認參數。

假設我不想explicitly bind所有這些默認設置,我相信這是不可能做到這一點,而不包括這樣的調用一個輔助函數或lambda。是否有一個提升包裝或TMP魔術以完全一般的方式爲我完成?像call_as<char(char)>(fp2)或更可能是call_as<int(const std::string&)>(std::stoi)甚至可以寫入包裝?

+3

你能只使用lambda在'transform'命令?最簡單,最乾淨。 –

+0

我寫了並刪除了一個關於「bind」的註釋,它已經是你正在尋找的包裝。然後,我想到你必須提供默認值綁定,從而重新定義它們。 –

+0

在考慮如何通過模板來混淆代碼之前,最好先準備好算法。所以,從算法開始。如果除了'EOF'值,否則'std :: toupper'調用會產生未定義的行爲。 –

回答

5

這很有趣,我做了類似的事情。我發現這樣做的最好方法是使用lambdas,如下所示,否則,您必須使用typedef來獲得正確的重載,並使用std :: bind來擺脫語言環境,或者不使用語言環境。然而,這個工作更乾淨:

static const std::locale loc; 
transform(in.begin(), in.end(), back_inserter(out), [&loc](char c) { 
    return std::toupper(c, loc); 
}); 

我使用靜態保存每個時間重新分配的努力。

或者你可以得到一個typedef,做:

std::bind((LocaleCompare)std::toupper, std::placeholders::_1, loc); // UGLY! 
0

你可以創建一個functon指針類型的typedef,然後強制轉換該函數。

typedef char (*LocaleToUpper)(char, const std::locale&) ; 
char (*fp2)(char, const std::locale&) = (LocaleToUpper)toupper;