3

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

Community
  • 1
  • 1
Rich
  • 1,669
  • 2
  • 19
  • 32

2 Answers2

3

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).

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 1
    `std::isgraph` is overloaded? what is the other signature it has? how come I couldn't find it on cppreference? – Rich Nov 25 '15 at 03:45
  • @Rich: I think I maybe erred here. The error message says it's overloaded with the OPs C++ implementation. ANd there is a `std::graph` function template. But I can so far not find information that it can be specialized for `char` and `wchar_t`. Checking... And thanks! – Cheers and hth. - Alf Nov 25 '15 at 03:50
  • http://en.cppreference.com/w/cpp/string/byte/isgraph http://en.cppreference.com/w/cpp/locale/isgraph – Neil Kirk Nov 25 '15 at 03:55
  • OK, it turns out the answer text is technically correct. A function template of the same name is sufficient to prevent successful overload resolution. I was doubting myself here, thinking that the concrete function should win over the template, but I was wrong thinking that I was wrong. Uh. – Cheers and hth. - Alf Nov 25 '15 at 04:00
0

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

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • Neil, are you the Neil from years ago? – Cheers and hth. - Alf Nov 25 '15 at 04:04
  • is the header somehow included in by other headers? Is there any way to find out which headers include a certain other header file (other than looking at the source code if possible)? – Rich Nov 25 '15 at 04:04
  • @Cheersandhth.-Alf Possibly, I've been Neil for quite some time. Could you elaborate? – Neil Kirk Nov 25 '15 at 04:20
  • @NeilKirk: Sorry, I think I confused you with Neil Butterworth. He was one of the high profile ["I'm leaving Stack Overflow" users](http://kera.name/articles/2012/03/why-i-broke-up-with-stack-overflow/). 'Races in Orbit, the author of the linked to I'm-also-leaving-article, is back. I thought you might be the Butterworth Neil coming back. In a way, that's compliment. IIRC, long after NB left one could recognize his answers as highly upvoted no-username answers. – Cheers and hth. - Alf Nov 27 '15 at 04:17