find_if() problem with string

I get a compilation error when using find_if() with a string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <algorithm>            /// find_if()
#include <iostream>
#include <cctype>               /// islower()

using namespace std;


void first_lower(string& s)
{
    auto p = find_if(s.begin(), s.end(),
                     islower);
}


int main()
{

    return 0;
}


link: http://cpp.sh/64vet

The compilation error is:


In function 'void first_lower(std::string&)':
no matching function for call to 'find_if(std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unresolved overloaded function type>)'
note: candidate is:
note: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate)
     find_if(_InputIterator __first, _InputIterator __last,
     ^
note:   template argument deduction/substitution failed:
11:29: note:   couldn't deduce template parameter '_Predicate'


I am unable to identify the problem here.

Any clues?

Thanks.
There are two visible overloads of std::islower; and template argument deduction fails.

<cctyype> http://en.cppreference.com/w/cpp/string/byte/islower
<locale> http://en.cppreference.com/w/cpp/locale/islower

The second overload could have been indirectly included by <iostream>
The problem is that there are two versions of std::islower.

http://en.cppreference.com/w/cpp/string/byte/islower
http://en.cppreference.com/w/cpp/locale/islower

You can either use a lambda, in which case the correct function will be determined by the arguments that you pass to the function.

1
2
auto p = find_if(s.begin(), s.end(),
                 [](char c){ return islower(c); });

Or you can cast to a function pointer of the correct type.

1
2
auto p = find_if(s.begin(), s.end(),
                 static_cast<int(*)(int)>(islower));
Last edited on
Thanks for the reply.

I've tried it and it works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <algorithm>            /// find_if()
#include <iostream>
#include <cctype>                /// islower()

using namespace std;


void first_lower(const string& s)
{
    auto p = find_if(s.begin(), s.end(),
                     [] (char c)
                     {
                         return islower(c);
                     }
                    );
    if (p != s.end())                     
        cout << *p << endl;
}


int main()
{
    first_lower(string {"Hello"});
    first_lower(string {"dear"});
}


http://cpp.sh/4inws
Using scope-resolution (::) with the islower function object also makes the OP work:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <algorithm>            /// find_if()
#include <iostream>
#include <cctype>                /// islower()

using namespace std;


void first_lower(const string& s)
{
    auto p = find_if(s.begin(), s.end(),::islower);
    if (p != s.end())
        cout << *p << endl;
}

int main()
{
    first_lower(string {"Hello"});
    first_lower(string {"dear"});
}

http://coliru.stacked-crooked.com/a/25392f96e5c7eb53
There is no guarantee that the header <cctype> would provide its declarations and definitions within the global namespace. (It may do so, but it is not required to do so.)

To use use ::islower in a portable manner, #include <ctype.h>. This header assuredly provides its declarations and definitions within the global namespace. (It may also provide these names within the namespace std, but it is not required to do so.)
This header assuredly provides its declarations and definitions within the global namespace.

This is interesting, is there a list of namespaces associated with the various header files? Thanks
See 20.5.1.1 and 20.5.1.2 (Library-wide requirements) http://eel.is/c++draft/requirements
and Annex D.5 (deprecated features, normative) http://eel.is/c++draft/depr.c.headers
Last edited on
Thank you all. My program runs fine now.
Topic archived. No new replies allowed.