Given the code:
#include <iostream>
#include <cctype>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string s("ABCDEFGHIJKL");
transform(s.begin(),s.end(),s.begin(),tolower);
cout<<s<<endl;
}
I get the error:
No matching function for call to
transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)
What does "unresolved overloaded function type" mean?
If I replace the tolower
with a function I wrote, it no longer errors.
David already identified the issue, namely a conflict between:
<cctype>
'sint tolower(int c)
<locale>
'stemplate <typename charT> charT tolower(charT c, locale const& loc)
Using the first is much easier, but is undefined behavior (unfortunately) as soon as you deal with anything else than lower-ascii (0-127) in signed chars. By the way, I do recommend defining
char
as unsigned.The template version would be nice, but you would have to use
bind
to provide the second parameter, and it's bound to be ugly...So, may I introduce the Boost String Algorithm library ?
And more importantly:
boost::to_lower
:)Expressiveness is desirable.
Browsing my
<ctype>
header from gcc 4.2.1, I see this:...
...
...
So it looks like
tolower
exists in both thestd
(from<cctype>
) and root (from<ctype.h>
) namespaces. I'm not sure what the#pragma
does.Try using
::tolower
. This fixed the problem for me.The problem most probably relates with multiple overloads of
tolower
and the compiler is unable to select one for you. You can try qualifying it to select an specific version of it, or you might need to provide a function pointer cast to disambiguate. Thetolower
function can be present (multiple different overloads) in the<locale>
header, as well as in<cctype>
.Try:
That can be done in a single line with a cast, but it is probably harder to read:
Let's look at a list of options starting with the worst and moving to the best. We'll list them here and discuss them below:
transform(cbegin(s), cend(s), begin(s), ::tolower)
transform(cbegin(s), cend(s), begin(s), static_cast<int(*)(int)>(tolower))
transform(cbegin(s), cend(s), begin(s), [](const unsigned char i){ return tolower(i); })
The code in your question,
transform(s.begin(), s.end(), s.begin(), tolower)
will produce an error like:The reason that you were getting an "unresolved overloaded function type" is there are 2
tolower
s in thestd
namespace:locale
library definestemplate <typename T> T tolower(T, const locale&)
cctype
library definesint tolower(int)
1 is the solution offered by davka. It addresses your error by leveraging the fact that
locale
'stolower
is not defined in the global namespace.Depending upon your situation
locale
'stolower
may merit consideration. You can find a comparison of thetolower
s here: Which tolower in C++?Unfortunately 1 depends upon
cctype
'stolower
being defined in the global namespace. Let's look at why that may not be the case:You are rightly using
#include <cctype>
, as doing#include <ctype.h>
has been deprecated in C++: http://en.cppreference.com/w/cpp/headerBut the C++ standard states in D.3[depr.c.headers]2 of the declarations in the headers:
So the only way that we can guarantee our code is implementation independent is to use a
tolower
fromnamespace std
. 2 is the solution offered by David Rodríguez - dribeas. It leverages the fact thatstatic_cast
can:Before we move on, let me comment that if you find
int (*)(int)
to be a bit confusing you can read more on function pointer syntax here.Sadly there is one other issue with
tolower
's input argument, if it:You are using a
string
which uses elements of type:char
. The standard states ofchar
specifically 7.1.6.2[dcl.type.simple]3:So if the implementation defined a
char
to mean asigned char
then both 1 and 2 would result in Undefined Behavior for all characters corresponding to negative numbers. (If an ASCII character encoding is being used the characters corresponding to negative numbers are Extended ASCII.)The Undefined Behavior can be avoided by converting the input to an
unsigned char
before passing it totolower
. 3 accomplishes that using a lambda that accepts anunsigned char
by value, then passes it totolower
implicitly converting toint
.To guarantee Defined Behavior on all compliant implementations, independent of character encoding, you'll need to use
transform(cbegin(s), cend(s), begin(s), [](const unsigned char i){ return tolower(i); })
or something similar.