你如何使用std :: not1和std :: not2?

时间:2015-03-24 17:16:31

标签: c++ c++11

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

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

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

3 个答案:

答案 0 :(得分:9)

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

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

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

int

是一种正确的方法。否则

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

更容易理解 - 更短。

答案 1 :(得分:4)

  

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

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

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

答案 2 :(得分:-1)

其中一种方法是使用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