g++ string remove_if error
-
27-10-2019 - |
Pergunta
Here's the code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string word="";
getline(cin,word);
word.erase(remove_if(word.begin(), word.end(), isspace), word.end());
word.erase(remove_if(word.begin(), word.end(), ispunct), word.end());
word.erase(remove_if(word.begin(), word.end(), isdigit), word.end());
}
When compiled in VS 2010, it works perfectly fine. Compiled with G++ it says:
hw4pr3.cpp: In function `int main()':
hw4pr3.cpp:20: error: no matching function for call to `remove_if(__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> > >, <unknown type>)'
hw4pr3.cpp:21: error: no matching function for call to `remove_if(__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> > >, <unknown type>)'
hw4pr3.cpp:22: error: no matching function for call to `remove_if(__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> > >, <unknown type>)'
Solução
Add ::
to the beginning of isspace
, ispunct
and isdigit
, since they have overloads that the compiler can't decide on which to use:
word.erase(remove_if(word.begin(), word.end(), ::isspace), word.end());
word.erase(remove_if(word.begin(), word.end(), ::ispunct), word.end());
word.erase(remove_if(word.begin(), word.end(), ::isdigit), word.end());
Outras dicas
Add #include <cctype>
(and say std::isspace
etc. if you aren't abusing namespace std;
).
Always include all headers that you need, and don't rely on hidden nested inclusions.
You may also have to disambiguate the overload from the other one in <locale>
. Do this by adding an explicit cast:
word.erase(std::remove_if(word.begin(), word.end(),
static_cast<int(&)(int)>(std::isspace)),
word.end());
For me it compiles using g++ if I do either of the following:
- remove
using namespace std;
and changestring
tostd::string
; or - change
isspace
to::isspace
(etc.).
Either of these will cause isspace
(etc.) to be taken from the main namespace, instead of being interpreted as possibly meaning std::isspace
(etc.).
The problem is that std::isspace(int) takes an int as a parameter but a string is composed of char. So you have to write your own function as:
bool isspace(char c) { return c == ' '; }
The same applies to the other two functions.