我试图将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::使用。但是,我编写了另一个程序,发现ispunctstd::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/

10-12 23:56