为tolower禁用不需要的重载

时间:2014-12-03 13:44:02

标签: c++ c++11

在研究时,我发现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;

也不起作用。

现在这是毫无意义的练习,但这可能吗?

1 个答案:

答案 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的地址。