我正在尝试使用 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++ 语言环境有关,但我对它们不太熟悉。
谢谢!
最佳答案
有一个函数int isxdigit(int)
在 C 标准库中( header <ctype.h>
,C++ 等效 header <cctype>
)。这可以在 count_if
中明确使用.
如果您包括 <ctype.h>
, 这个函数在全局命名空间中结束。如果包括 <cctype>
, 它保证放在命名空间 std
中;但由于它是一个 C 库函数,您的 C++ 标准库(实现)也可以将其放入全局命名空间。
另一方面,有一个函数模板 isxdigit
在 C++ 标准库中( header <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;
}
这会自动选择合适的重载。
在 C++1y 中,您可以使用通用 lambda:
int main()
{
string s = "123abc";
cout << count_if(s.begin(), s.end(), [](auto p){ return isxdigit(p); })
<< endl;
}
关于C++ count_if 函数 - 无法推断模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20019636/