我正在尝试使用C ++的count_if
函数来查看std::string
中有多少个十六进制数字。当我尝试以下内容时:
string s = "123abc";
cout << count_if(s.begin(), s.end(), isxdigit) << endl;
我收到以下错误:
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)
但是,当我使用::isxdigit
时,程序会编译并运行。我知道预先::
与在全局范围内使用isxdigit
有关,但我不确定为什么它在这种情况下会有所帮助。我也认为它与C ++语言环境有关,但我不太熟悉它们。
谢谢!
答案 0 :(得分:6)
C标准库中有一个函数int isxdigit(int)
(标题<ctype.h>
,C ++等效标题<cctype>
)。这可以在count_if
中明确使用。
如果包含<ctype.h>
,则此函数最终在全局命名空间中。如果您包含<cctype>
,则保证将其放入名称空间std
;但由于它是一个C库函数,因此允许您的C ++标准库(实现)将其放入全局命名空间。
另一方面,C ++标准库(标题isxdigit
)中有一个函数 template <locale>
。这只是放在命名空间std
中。
您收到此错误的原因是因为某个地方可能有using namespace std;
,或者std::isxdigit
<locale>
可见isxdigit
。然后,名称count_if
引用一组重载函数。由于有多个候选者,并且static_cast<int(*)(int)>(&isxdigit)
接受了其中许多候选者,因此编译器现在无法超载您的意思。
您可以指定哪个重载,例如,使用::isxdigit
。
使用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;
}
时,只找到一个函数,因此编译器知道其类型并可以推导出模板参数。
比手动选择重载更有用的解决方案是使用带有泛型函数调用操作符的函数对象:
int main()
{
string s = "123abc";
cout << count_if(s.begin(), s.end(), [](auto p){ return isxdigit(p); })
<< endl;
}
这会自动选择适当的过载。
在C ++ 1y中,你可以使用泛型lambda:
{{1}}