0

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

rogrp6
  • 47
  • 1
  • 5
  • 2
    Well the compiler probably did you a favor since using `using namespace std` is very bad practice – Shidouuu Mar 26 '21 at 00:28
  • There are indeed multiple overloads of `isalpha()`, and your `using namespace std` is pulling them into the local namespace, so you would have to clarify to the compiler which overload you want to use for the predicate. Better to use a lambda instead that calls `isalpha()` with the desired parameters (as your commented code shows), let overload resolution do its job. And [get rid of the `using namespace std`](https://stackoverflow.com/questions/1452721/) statement. – Remy Lebeau Mar 26 '21 at 00:28
  • According to cppreference you shouldn't use isalpha by itself anyway https://en.cppreference.com/w/cpp/string/byte/isalpha – QuentinUK Mar 26 '21 at 00:37
  • Also, never put more than one statement in one line, this is considered bad practice and makes the code harder to read – Shidouuu Mar 26 '21 at 00:37
  • I tried compiling the same code you posted using MSVC and it compiled and worked just fine. Perhaps it's a problem with g++? – Shidouuu Mar 26 '21 at 00:46
  • @Shidouuu It's a problem with the program. Compiling in one compiler doesn't mean that the program is correct. – eerorika Mar 26 '21 at 00:51

3 Answers3

2

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.

Zoso
  • 3,273
  • 1
  • 16
  • 27
1

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.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

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; 
    }
}

rogrp6
  • 47
  • 1
  • 5