C++ using standard algorithms with strings, count_if with isdigit, function cast

algorithm, c++, casting, function, string

Solution

You can resolve the function by using a static cast. Alternatively if this is something you want to do a lot you can use a template to resolve it:

#include <string>
#include <cctype>
#include <algorithm>

unsigned count(const std::string& s) {
  return std::count_if(s.begin(), s.end(), static_cast<int(*)(int)>(std::isdigit));
}

template <int(*Pred)(int)> 
unsigned foo(const std::string& s) {
  return std::count_if(s.begin(), s.end(), Pred);
}

int main() {
  count("");
  foo<std::isdigit>("");
  foo<std::isprint>("");
}

`static_cast` is the "usual" way of resolving ambiguous - it always does what you expect and can be part of a larger expression.

Problem

I want to count all numbers in string in shortest code way. I tried that way: ``` #include <string> #include <algorithm> unsigned countNumbers(const std::string s) { return count_if(s.begin(), s.end(), isdigit); } ``` Error message is: ``` a.cc: In function ‘unsigned int countNumbers(std::string)’: a.cc:5:45: error: no matching function for call to ‘count_if(std::basic_string<char>::const_iterator, std::basic_string<char>::const_iterator, <unresolved overloaded function type>)’ a.cc:5:45: note: candidate is: /usr/include/c++/4.6/bits/stl_algo.h:4607:5: note: template<class _IIter, class _Predicate> typename std::iterator_traits<_InputIterator>::difference_type std::count_if(_IIter, _IIter, _Predicate) ``` I know that count_if() wants function like: bool (*f)(char); as a third argument, so I tried to cast the function: ``` unsigned countNumbers(const std::string s) { return count_if(s.begin(), s.end(), reinterpret_cast<bool (*)( char )>(isdigit)); } ``` Error message is: ``` a.cc: In function ‘unsigned int countNumbers(std::string)’: a.cc:5:80: error: overloaded function with no contextual type information ``` I tried also a bit longer version, which gives the same compilation error: ``` unsigned countNumbers(const std::string s) { typedef bool ( * f_ptr )( char ); f_ptr ptr = reinterpret_cast<f_ptr>(isdigit); return count_if(s.begin(), s.end(), ptr); } ``` The solution that I want to avoid is to create a function which would be an adapter: ``` #include <string> #include <algorithm> bool is_digit(char c) { return isdigit(c); } unsigned countNumbers(const std::string s) { return count_if(s.begin(), s.end(), is_digit); } ``` My question is how can I use functions int(*f)(int) in std::algorithm's functions which want bool(*f)(int) without creating adapter-functions and without using lambda expressions? I have more issues which would be solved when I get know how to solve the problem, e.g.: - Check if string is printable: find_if_not(s.begin(), s.end(), isprint) - Check if string contains ",.!?...": find_if (s.begin(), s.end(), ispunct) and more... I just want to know how to have much more string possibilities in standard C++ thanks to std::algorithms I was searching at the Internet long time, I found similar problem, but I found no solution

Original source