2014-12-03 30 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