在研究时,我发现Why “transform(s.begin(),s.end(),s.begin(),tolower)” can't be complied successfully?,解决方法是使用::tolower
。作为练习,我想看看是否可以禁用(在 locale 头文件中)重载并使用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 :(得分: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
的地址。