I'm trying to use C++'s count_if
function to see how many hex digits are in a std::string
. When I try the following:
string s = "123abc";
cout << count_if(s.begin(), s.end(), isxdigit) << endl;
I get the following error:
count.cpp:14:13: error: no matching function for call to 'count_if'
cout << count_if(s.begin(), s.end(), isxdigit) << endl;
^~~~~~~~
/usr/include/c++/4.2.1/bits/stl_algo.h:448:5: note: candidate template ignored: couldn't infer
template argument '_Predicate'
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
However, when I use ::isxdigit
, the program compiles and runs. I know prepending the ::
has something to do with using the isxdigit
in the global scope, but I'm not sure why it helps in this case. I also think it has something to do with C++ locales, but I'm not too familiar with them.
Thanks!
There is a function int isxdigit(int)
in the C Standard Library (header <ctype.h>
, C++ equivalent header <cctype>
). This can be used unambiguously in count_if
.
If you include <ctype.h>
, this function ends up in the global namespace. If you include <cctype>
, it's guaranteed to be put in namespace std
; but as it's a C-library function, your C++ Standard Library (implementation) is allowed to put it into the global namespace as well.
On the other hand, there is a function template isxdigit
in the C++ Standard Library (header <locale>
). This is only put into namespace std
.
The reason why you get this error is because you probably have a using namespace std;
somewhere, or otherwise make std::isxdigit
from <locale>
visible. Then, the name isxdigit
refers to a set of overloaded functions. As there are multiple candidates, and count_if
accepts many of them, the compiler cannot now which overload you meant.
You can specify which overload was meant, for example, by using static_cast<int(*)(int)>(&isxdigit)
.
When you use ::isxdigit
, only one function is found, so the compiler knows its type and can deduce the template parameter.
A more useful solution than manually choosing the overload is to use a function object with a generic function call operator:
struct Isxdigit
{
template<class T>
bool operator()(T const& p) const
{
using std::isxdigit;
return isxdigit(p);
}
};
int main()
{
string s = "123abc";
cout << count_if(s.begin(), s.end(), Isxdigit()) << endl;
}
This automatically selects the proper overload.
In C++1y, you could use generic lambdas:
int main()
{
string s = "123abc";
cout << count_if(s.begin(), s.end(), [](auto p){ return isxdigit(p); })
<< endl;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.