我试图将std::ispunct
作为最后一个参数传递给remove_copy_if
,但发现编译失败。
但是,如果我通过ispunct
(只是删除了std::
),程序将按预期编译并运行。
码:
#include<iostream>
#include<map>
#include<cctype>
#include<algorithm>
#include<iterator>
using std::map;
using std::string;
string strip_punct(const string &s) {
string target;
remove_copy_if(s.begin(), s.end(), std::back_inserter(target), std::ispunct);
return target;
}
int main() {
string word = "abc.";
string target = strip_punct(word);
std::cout << "target: " << target << "\n";
return 0;
}
错误信息:
$ g++ --std=c++11 -o problem_11_4.out problem_11_4.cpp
problem_11_4.cpp: In function 'std::string strip_punct(const string&)':
problem_11_4.cpp:12:80: error: no matching function for call to 'remove_copy_if(std::__cxx11::basic_string<char>::const_iterator, std::__cxx11::basic_string<char>::const_iterator, std::back_insert_iterator<std::__cxx11::basic_string<char> >, <unresolved overloaded function type>)'
12 | remove_copy_if(s.begin(), s.end(), std::back_inserter(target), std::ispunct);
| ^
In file included from /usr/local/Cellar/gcc/9.2.0_1/include/c++/9.2.0/algorithm:62,
from problem_11_4.cpp:4:
/usr/local/Cellar/gcc/9.2.0_1/include/c++/9.2.0/bits/stl_algo.h:703:5: note: candidate: 'template<class _IIter, class _OIter, class _Predicate> _OIter std::remove_copy_if(_IIter, _IIter, _OIter, _Predicate)'
703 | remove_copy_if(_InputIterator __first, _InputIterator __last,
| ^~~~~~~~~~~~~~
/usr/local/Cellar/gcc/9.2.0_1/include/c++/9.2.0/bits/stl_algo.h:703:5: note: template argument deduction/substitution failed:
problem_11_4.cpp:12:80: note: couldn't deduce template parameter '_Predicate'
12 | remove_copy_if(s.begin(), s.end(), std::back_inserter(target), std::ispunct);
| ^
我在SO上搜索后发现以下问题:Why std:: is not needed when using ispunct() in C++?
这很有帮助,现在我知道
ispunct
可以不带std::
使用。但是,我编写了另一个程序,发现ispunct
和std::ispunct
单独使用时(而不是作为参数)都可以很好地工作。我仍然不明白为什么将std::
用作参数时不允许使用ispunct
。 最佳答案
std::ispunct
是重载函数。 <cctype>
中存在一个版本,而<locale>
中存在一个版本。即使您不包括<locale>
,您的include之一也会导致重载并导致推导失败,因为重载的函数无法推导类型。
解决此问题的方法是将std::ispunct
包装在lambda中,因为在lambda主体中,编译器可以执行重载解析并调用正确的函数。那会给你
remove_copy_if(s.begin(),
s.end(),
std::back_inserter(target),
[](unsigned char ch){ return std::ispunct(ch); }); // use unsigned char here to stop any possible UB
关于c++ - 将std::ispunct作为参数传递给remove_copy_if()无法编译,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58527598/