I try to understand how to use std::tolower
...
#include
#include
#include
#include
std::tolower
is overloaded in C++, it's declared in
as
int tolower(int);
and also in
as
template CharT tolower(CharT, const locale&);
so when you say "std::tolower
" you get an ambiguous reference to an overloaded function.
- Why
::tolower
version is working?
When you include
the one-argument overload is declared in namespace std
and might also be declared in the global namespace, depending on the compiler. If you include
then it's guaranteed to be included in the global namespace, and ::tolower
will work (although note Dietmar's points about when it's not safe). The two-argument overload from
is never declared in the global namespace, so ::tolower
never refers to the two-argument overload.
2. Why
std::tolower
is not working in std::transform?
See above, it's an overloaded name.
3. What
static_cast
really is trying to do?(std::tolower))
It tells the compiler you want the int std::tolower(int)
overload, not any other overload of std::tolower
.
Why does it work with GCC and not with Visual Studio 2013?
Probably because you didn't include
, or (less likely) it could be a Visual Studio bug.
4. How could I use
std::lower
instd::transform
with Visual Studio 2013 then?
If you know you only have characters with values between 0 and 127 then you can include
and use ::tolower
(because the two-argument version is not declared in the global namespace, only in namespace std
) or disambiguate which overload you want with the static cast. An alternative to the cast is to use a local variable:
typedef int (*tolower_type)(int);
tolower_type tl = &std::tolower;
std::transform(b, e, b, tl);
A safer and portable alternative is to use a custom function object (or lambda expression) to call the desired overload safely:
std::transform(b, e, b, [](unsigned char i) { return std::tolower(i); });
This uses std::tolower
with an argument, so the compiler can do overload resolution to tell which overload you want to call. The parameter is unsigned char
to ensure we never pass a char
with a negative value to tolower(int)
, because that has undefined behaviour.
See http://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.simple for more details.