2014-12-03 29 views
3

在研究時,我發現Why 「transform(s.begin(),s.end(),s.begin(),tolower)」 can't be complied successfully?,並且解決方案是使用::tolower。作爲一個練習,我想看看我是否可以禁用它(在區域設置頭文件中)並且使用std::tolower。首先,我們從簡單的開始:禁用不必要的過載保護

template <typename charT> charT tolower(charT c, std::locale const& loc) = delete; 

int main() 
{ 
    std::vector<char> chars = { 'a', 'D', 'c', 'b' }; 
    std::transform(chars.begin(), chars.end(), chars.begin(), std::tolower); 
} 

編譯器不能推斷正確的過載。所以我們提供char模板:

std::transform(chars.begin(), chars.end(), chars.begin(), std::tolower<char>); 

所以我們又回到原點了。我知道這是未定義的行爲,但我想我可以把它放到空間std:

namespace std { 
template <typename charT> charT tolower(charT c, std::locale const& loc) = delete; 
} 

現在,編譯器說,我重新定義的功能。

using std::tolower; 
template <typename charT> charT tolower(charT c, std::locale const& loc) = delete; 

也不起作用。

現在這是毫無意義的練習,但是這可能嗎?

+0

顯式刪除函數不會將其從重載解析中移除;這隻意味着如果選擇了超載,則會出現錯誤。 – 2014-12-03 14:23:36

回答

5

您不能禁用其他的過載,但也有很多的方法,以確保正確的選擇:

int (*lower)(int) = std::tolower; 
std::transform(chars.begin(), chars.end(), chars.begin(), lower); 

std::transform(chars.begin(), chars.end(), chars.begin(), static_cast<int(*)(int)>(std::tolower)); 

std::transform(chars.begin(), chars.end(), chars.begin(), [](int c) { return std::tolower(c); }); 

struct ToLower { 
    int operator()(int c) const { return std::tolower(c); } 
}; 
std::transform(chars.begin(), chars.end(), chars.begin(), ToLower{}); 

前兩種形式告訴編譯器如何從重載集合中選擇正確的重載,因爲只有一個重載可以轉換爲該類型的函數指針。

第二個兩種形式創建一個包裝器,調用tolower,以便正常的重載解析找到正確的重載解析器,並且不需要獲取地址tolower