This question already has answers here:
std::transform() and toupper(), no matching function
(3 answers)
Closed 9 years ago.
can anyone tell me what is the mistake in this program
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string str = "Now";
transform(str.begin(), str.end(), str.begin(), toupper);
cout<<str;
return 0;
}
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>)'
compilation terminated due to -Wfatal-errors."
There are two functions with name toupper. One from cctype header:
int toupper( int ch );
And second from locale header:
charT toupper( charT ch, const locale& loc );
Compiler can't deduce which function should be used, since you allow namespace std. You should use scope resolution operator(::) to choose function defined in global space:
transform(str.begin(), str.end(), str.begin(), ::toupper);
Or, better: Do not use using namespace std.
Thanks to #Praetorian -
This is probably the cause of the error, but adding :: may not always
work. If you include cctype toupper is not guaranteed to exist in the
global namespace. A cast can provide the necessary disambiguation
static_cast<int(*)(int)>(std::toupper)
So, the call should look like:
std::transform
(
str.begin(), str.end(),
str.begin(),
static_cast<int(*)(int)>(std::toupper)
);
In order to use toupper, you need to include header file:
#include <cctype>
You also need to include header file:
#include <string>
The problem is the std::toupper takes int as parameter, while std::transform will pass char into the function, therefore, it has a problem (by courtesy of #juanchopanza).
You may try to use:
#include <functional>
std::transform(s.begin(), s.end(), s.begin(), std::ptr_fun<int, int>(std::toupper));
See example code from std::transform
Or you can implement your own toupper that takes char as argument.
As the compiler has buried in its error message, the real problem is that toupper is an overloaded function, and the compiler can't figure out which one you want. There's the C toupper(int) function which may or may not be a macro (may not in C++, but does the C library care?), and there's std::toupper(char, locale) from (pulled in by without doubt), which you made available globally with your using namespace std;.
Tony's solution works because he accidentally resolved the overloading issue with his separate function.
Related
I can't understand why I have this error, apparently the isalpha function is redeclared twice (my editor marks me: "2 more overloads") but I don't understand why, this is my code:
#include <iostream>
#include <set>
#include <algorithm>
#include <ctype.h>
#include <string>
using namespace std;
int main(){
cin.tie(nullptr);ios_base::sync_with_stdio(false);
string line;
string::iterator prev, act;
while(cin>>line){
// act = find_if(line.begin(), line.end(), [](int x) {return isalpha(x);}); // GOOD
act = find_if(line.begin(), line.end(), isalpha); // ERROR
cout<<*act<<endl;
}
}
I use g++ (MinGW.org GCC-6.3.0-1) 6.3.0
Error:
1215.cpp: In function 'int main()':
1215.cpp:14:56: error: no matching function for call to 'find_if(std::__cxx11::basic_string<char>::iterator, std::__cxx11::basic_string<char>::iterator, <unresolved overloaded function type>)'
act = find_if(line.begin(), line.end(), isalpha); // ERROR
^
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\algorithm:62:0,
from 1215.cpp:3:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:3808:5: note: candidate: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate)
find_if(_InputIterator __first, _InputIterator __last,
^~~~~~~
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:3808:5: note: template argument deduction/substitution failed:
1215.cpp:14:56: note: couldn't deduce template parameter '_Predicate'
act = find_if(line.begin(), line.end(), isalpha); // ERROR
Note: if I don't use the "using namespace std" the code compiles and executes correctly.
Thanks in advance for any answers or advice
This is what might be happening.
There's an isalpha() in the <cctype> header under the std namespace and another isalpha() in the <locale> header under the very same std namespace. using namespace std pulls both into the your scope and thus the ambiguity while deducing the template.
Moral of the story: Avoid using using namespace std.
I can't understand why I have this error, apparently the isalpha function is redeclared twice (my editor marks me: "2 more overloads") but I don't understand why
Two overloads are declared, because the standard says that there are two overloads.
A good solution is to use a lambda, as you did in the comment. Unlike creating a function pointer, calling the function in the lambda allows the call to be resolved to the correct overload based on the passed arguments.
Your lambda should be improved though: Change the type of the parameter to unsigned char. This is needed because char may be a signed type, and if the value of a char is negative, then it will have a value outside the range of unsigned char, and passing a value outside the range of unsigned char into islpha will result in undefined behaviour. Fixed example:
auto isalpha = [](unsigned char c){
return std::isalpha(c);
};
act = find_if(line.begin(), line.end(), isalpha);
Also, remove the line using namespace std.
To complete # Zoso's answer:
Inside <iostream> are included <cctype> and locale_facets.h both define different std::isalpha functions .
Also, inside <cctype> includes <ctype.h> (which is in fact explicitly included in the example) and <ctype.h> defines an isalpha function (without the std namespace).
So one way to solve the problem is to call the isalpha function of<ctype.h>, for this it is necessary to exit the current namespace (std) with :: operator.
This code works:
#include <iostream>
#include <algorithm>
#include <ctype.h>
#include <string>
using namespace std;
int main(){
cin.tie(nullptr);ios_base::sync_with_stdio(false);
string line;
string::iterator prev, act;
while(cin>>line){
act = find_if(line.begin(), line.end(), ::isalpha);
cout<<*act<<endl;
}
}
I tried to use std::isgraph from <cctype> as a predicate in find_if. But compiler errored out saying:
error: no matching function for call to ‘find_if(__gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, __gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, < unresolved overloaded function type>)’
I have used using namespace std; and from my understanding there will be two isgraph functions visible in the global namespace. So ::isgraph or simply isgraph should be ambiguous and std::isgraph should not be ambiguous. On the contrary, using ::isgraph is OK while std::isgraph is not.
Can someone explain what I missed? A few related questions are What are the function requirements to use as the predicate in the find_if from the <algorithm> library? and C++ using standard algorithms with strings, count_if with isdigit, function cast. But they didn't answer why explicitly specifying std:: still doesn't resolve to the function in the std namespace.
EDIT:
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string root_line = "hello";
auto ind = distance(root_line.begin(), find_if(root_line.begin(), root_line.end(), std::isgraph));
cout << ind;
return 0;
}
I compiled the above code with g++ -std=c++11 of version 4.8.4
std::isgraph is overloaded.
To resolve the ambiguity you could cast it to the relevant function pointer type.
But in order to use it correctly the argument should be converted to unsigned char, so better define a wrapper function:
using Byte = unsigned char;
auto is_graphical( char const ch )
-> bool
{ return !!isgraph( Byte( ch ) ); }
Note that this only works with single-byte encodings, and that it depends on the current locale at the C level (see setlocale).
There is a std::isgraph defined in <cctype> and a different std::isgraph defiend in <locale>. Using overloaded functions as functors can be a pain as the compiler has difficulty figuring out which version of the function you want. You can resolve the ambiguity by casting, or using a lambda or named wrapper function as suggested by #Cheersandhth.-Alf
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string root_line = "hello";
auto ind = std::distance(root_line.begin(), std::find_if(root_line.begin(), root_line.end(), static_cast<int(*)(int)>(std::isgraph)));
std::cout << ind;
}
Live example: http://ideone.com/heSSEZ
//for( unsigned int i=0; i < c.size(); i++ ) tolower( c[i] );
for_each( c.begin(), c.end(), tolower );
I am trying to use a for_each loop in place of the for loop for an assignment.
I am unsure why I am getting this error message:
In function âvoid clean_entry(const std::string&, std::string&)â:
prog4.cc:62:40: error: no matching function for call to âfor_each(std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unresolved overloaded function type>)â
Write:
for_each( c.begin(), c.end(), ::tolower );
Or :
for_each( c.begin(), c.end(), (int(*)(int))tolower);
I've faced this problem so many times that I'm tired of fixing this in my code, as well as in others' code.
Reason why your code is not working : there is another overloaded function tolower in the namespace std which is causing problem when resolving the name, because the compiler is unable to decide which overload you're referring to, when you simply pass tolower 1. That is why the compiler is saying unresolved overloaded function type in the error message, which indicates the presence of overload(s).
So to help the compiler in resolving to the correct overload, you've to cast tolower as
(int (*)(int))tolower
then the compiler gets the hint to select the global tolower function, which in other ways, can be used by writing ::tolower.
1. I guess you've written using namespace std in your code. I would also suggest you to not to do that. Use fully-qualified names in general.
By the way, I think you want to transform the input string into lower case, if so, then std::for_each wouldn't do that. You've to use std::transform function as:
std::string out;
std::transform(c.begin(), c.end(), std::back_inserter(out), ::tolower);
//out is output here. it's lowercase string.
1) You have using namespace std; somewhere in your code. The danger of importing the entire std namespace is that you don't necessarily know what you are getting. In this case, you have imported overloads of std::tolower.
Never type using namespace std;, even if your textbook or your instructor tells you to.
2) Since you are restricted from using std::transform, you could modify the string in place using std::for_each:
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
void
MakeLower(char& c)
{
c = std::tolower(c);
}
int
main ()
{
std::string c("Hello, world\n");
std::for_each(c.begin(), c.end(), MakeLower);
std::cout << c;
}
To my surprise the following code compiles:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <cctype>
int main() {
std::string s="nawaz";
std::string S;
std::transform(s.begin(),s.end(), std::back_inserter(S), ::toupper);
std::cout << S ;
}
I had expected it to fail because of the ::toupper which I believed should be in the std namespace. A quick check of cctype shows that it is but it is imported from the root namesapce (Mystery solved there).
namespace std
{
// Other similar `using` deleted for brevity.
using ::toupper;
}
So first problem solved but if I change the transform() line above too:
std::transform(s.begin(),s.end(), std::back_inserter(S), std::toupper);
I would now expect this to now also compile. But I get a compiler error:
kk.cpp:12: 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::cha
r_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'
Which with manual editing resolved too:
kk.cpp:12: error: no matching function for call to
`transform(iterator<std::string>,
iterator<std::string>,
std::back_insert_iterator<std::string>,
<unresolved overloaded function type>)'
What am I missing?
It doesn't work because there are overloads of std::toupper. You can fix it by casting to your desired function overload:
std::transform(s.begin(),s.end(), std::back_inserter(S),
(int(&)(int))std::toupper);
You're missing that C++ also adds new toupper functions in <locale> which is probably included implicitly by one of your other headers. Thus in the std:: namespace there are multiple overloads while in the global namespace there is only the old C version of the function.
That said it does still seem like g++ should be able to deduce the correct overload.
Like others said the problem is that std::toupper and friends are overloaded.
One way to fix this is to use a lambda.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main()
{
std::string s{ "This is a test" };
std::string S{};
std::transform(s.begin(), s.end(), std::back_inserter(S), [] (char ch){ return std::toupper(ch); });
std::cout << S;
return 0;
}
I realize this is an old post but as many, including myself, still encounter this issue, I hope my post will be helpful.
I'm trying to split a string using the method found in this thread, but I'm trying to adapt it to a wstring. However, I have stumbled upon a weird error. Check the code:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main(void)
{
wstring str(L"Börk börk");
wistringstream iss(str);
vector<wstring> tokens;
copy(istream_iterator<wstring>(iss), // I GET THE ERROR HERE
istream_iterator<wstring>(),
back_inserter< vector<wstring> >(tokens));
return 0;
}
The exact error message is:
error: no matching function for call to 'std::istream_iterator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, char, std::char_traits<char>, int>::istream_iterator(std::wistringstream&)'
I think it is saying that it can't instantiate the istream_iterator using the passed iss (which is a wistringstream instead of a istringstream). This is on a Mac using XCode and GCC 4.2. And AFAIK there is no wistring_iterator or anything like that.
It works perfectly when I'm using the non-wstring version. As you might see I have changed the declarations to use wstring, wistringstreams and vector<wstring>, just replaced everything to use the wide version.
What could cause this and why won't it accept the wstring-version?
Per the latter part of the error message, you have to override the default params 2 and 3 on istream_iterator() to match widechar usage elsewhere. In Visual C++ this version compiles OK for me:
copy(istream_iterator<wstring, wchar_t, std::char_traits<wchar_t> >(iss), // I DO NOT GET THE ERROR HERE
istream_iterator<wstring, wchar_t, std::char_traits<wchar_t> >(),
back_inserter< vector<wstring> >(tokens));