Disable unwanted overload for tolower
While researching, I found Why "transform (s.begin (), s.end (), s.begin (), tolower)" cannot be executed successfully? and the solution is to use ::tolower
. As an exercise, I want to see if I can disable this (in the locale header file) overload and use std::tolower
. First, we start simply:
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);
}
The compiler cannot output the correct overload. Therefore, we provide a char template:
std::transform(chars.begin(), chars.end(), chars.begin(), std::tolower<char>);
So we are back to square one. I know this is undefined behavior , but I thought I could put it in the std namespace:
namespace std {
template <typename charT> charT tolower(charT c, std::locale const& loc) = delete;
}
Now the compiler says that I am overriding the function.
using std::tolower;
template <typename charT> charT tolower(charT c, std::locale const& loc) = delete;
doesn't work either.
Now this is a pointless exercise, but is it possible?
source to share
You cannot disable another overload, but there are many ways to ensure the correct choice is made:
int (*lower)(int) = std::tolower;
std::transform(chars.begin(), chars.end(), chars.begin(), lower);
or
std::transform(chars.begin(), chars.end(), chars.begin(), static_cast<int(*)(int)>(std::tolower));
or
std::transform(chars.begin(), chars.end(), chars.begin(), [](int c) { return std::tolower(c); });
or
struct ToLower {
int operator()(int c) const { return std::tolower(c); }
};
std::transform(chars.begin(), chars.end(), chars.begin(), ToLower{});
The first two forms tell the compiler how to select the correct overload from the overload set, because only one of the overloads can be converted to a function pointer of that type.
The second two forms create a wrapper that calls tolower
, so that normal overload resolution finds the correct one and you don't need to take the address tolower
.
source to share