【问题标题】:How do you use std::not1 and std::not2?你如何使用 std::not1 和 std::not2?
【发布时间】:2015-03-25 02:16:16
【问题描述】:

目前,如果您想否定谓词,则必须使用 std::<algorithm>_if_not 变体或 lambda。但为了学术界,我想知道这是否可能:

std::string s("hello");
std::find_if(s.begin(), s.end(), std::not1(::ispunct));

不写自己的函数对象,如何让这段代码工作?

【问题讨论】:

  • 使用 Library Fundamentals v2 TS,std::not_fn(::ispunct)。但是请注意,为了使此调用对任何字符串都是安全的,字符应先转换为 unsigned char,然后再传递到 ispunct

标签: c++ c++11


【解决方案1】:

请记住,将chars 传递给来自 C 标准库的字符分类函数(以及 touppertolower)的正确方法是先将其转换为 unsigned char,然后再转换为 @ 987654325@。

为此使用std::refreference_wrapper 是轻量级的,而且是错误的。使用std::function<bool(int)>std::function<bool(char)> 更重量级,也是错误的。在所有这些情况下,字符串中的char 直接转换为int,这不是正确的做法。

如果你坚持不使用 lambda,那么

std::find_if(s.begin(), s.end(), std::not1(std::function<bool(unsigned char)>(::ispunct)));

是一种正确的方法。否则

std::find_if(s.begin(), s.end(), [](unsigned char c) { return !ispunct(c); });

更容易理解 - 并且更短。

【讨论】:

  • 您能否解释一下您的第一句话或提供参考资料?
  • @Pradhan 这些函数在 C 标准中定义。 WG14 N1570 §7.4 - “标题 &lt;ctype.h&gt; 声明了几个用于分类和映射字符的函数。在所有情况下,参数都是 int,其值应表示为 unsigned char 或应等于宏 EOF。如果参数有任何其他值,则行为未定义。"
【解决方案2】:

一元谓词类型必须定义一个成员类型argument_type,它可以转换为谓词的参数类型。

包装::ispunct最轻量级的方式是使用std::reference_wrapper

std::find_if(s.begin(), s.end(), std::not1(std::ref(::ispunct)));
                                           ^^^^^^^^

【讨论】:

    【解决方案3】:

    其中一种方法是使用 std::reference_wrapper 。这是一个演示程序

    #include <iostream>
    #include <functional>
    #include <string>
    #include <cctype>
    #include <algorithm>
    
    int main() 
    {
        std::string s( "...hello" );
    
        auto it = std::find_if( s.begin(), s.end(), std::not1( std::ref( ::ispunct ) ) );
    
        std::cout << *it << std::endl;
    
        return 0;
    }
    

    输出是

    h
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-27
      • 2020-04-24
      • 2014-08-20
      • 2012-11-02
      • 1970-01-01
      相关资源
      最近更新 更多