c++ - 将 std::ispunct 作为参数传递给 remove_copy_if() 无法编译

标签 c++ namespaces

我试图将 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 单独使用(不作为参数)时都能很好地工作。我仍然不明白为什么在将 ispunct 用作参数时不允许使用 std::

最佳答案

std::ispunct是一个重载函数。 <cctype> 中存在一个版本和 <locale> 中的一个版本.即使您不包括 <locale> ,您的其中一个包含会带来重载并导致推导失败,因为重载函数无法推导类型。

解决这个问题的方法是包装 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/

相关文章:

php - 代码点火器 : Sendmail cannot use Mailgun\Mailgun - it is not a trait Composer

.net - 类型 XX 存在于两个 DLL 中

php - 为什么在动态评估命名空间元素时必须使用完全限定名称?

PHP,命名空间中的新变量类

c++ - 为什么 View 和表的 sqlite 列有不同的名称?

c++ - 从派生类数组读取访问冲突

c++ - MPI_测试 : MPI_ERR_TRUNCATE

c++ - CMake 和 FIND_PACKAGE

c++ - 在 C++ 中将命名空间设为私有(private)

c++ - 是 !!在 C++ 中转换为 bool 的安全方法?