c++stringc++11findclang

How do I use find_if_not or find_if with isalpha/isspace and other <cctype> functions in C++?


According to this, find_if_not has been available since C++11, so I tried compiling with --std=c++11, and is defined in <algorithm> and is in the namespace std.

I have the following code:

#include <algorithm>
#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main(int argc, const char *argv[]) {
    string buffer;
    getline(cin, buffer);
    cout << buffer.substr(find_if(buffer.begin(), buffer.end(), isalnum) - buffer.begin()) << endl;
    return 0;
}

The idea is to simply echo the input but without any leading non-alphanumeric characters. However, I get a compiler error:

error: no matching function for
     call to 'find_if'
       cout << buffer.substr(find_if(buffer.begin(), buffer.end(), isal...
                             ^~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/algorithm:930:1: note: 
     candidate template ignored: couldn't infer template argument '_Predicate'
find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
^
1 error generated.

I then tried to use find_if_not(buffer.begin(), buffer.end(), isspace) instead and I the same 'no matching function' error.

How can I use these functions find_if and find_if_not? I tried using all the required headers and C++ version.

When I run g++ --version I get:

Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Solution

  • Your problem turns out to be

    using namespace std;
    

    as it introduces two different isspace functions into lookup, both std::isspace and isspace.

    When you use isspace it usually uses overload resolution rules to pick, but it cannot figure it out at template deduction time, so you get an error.

    Simply removing using namespace std; then adding std:: as required and your program compiles:

    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <cctype>
    //using namespace std;
    
    int main(int, const char *[]) {
        std::string buffer;
        std::getline(std::cin, buffer);
        std::cout << buffer.substr(std::find_if(buffer.begin(), buffer.end(), isalnum) - buffer.begin()) << std::endl;
        return 0;
    }
    

    as a general rule, using namespace std; causes more problems than it fixes.

    Live example.

    You can see this problem being described on the 2nd part of your error message:

    error: no matching function for
         call to 'find_if'
           cout << buffer.substr(find_if(buffer.begin(), buffer.end(), isal...
                                 ^~~~~~~
    /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/algorithm:930:1: note: 
         candidate template ignored: couldn't infer template argument '_Predicate'
    find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
    ^
    1 error generated.
    

    "couldn't infer template argument" (the type of the 3rd argument passed to find_if, aka isspace).

    The compiler can't resolve the overload, so can't figure out what type _Predicate should be.