How do you use std :: not1 and std :: not2?

Currently, if you want to undo a predicate, you need to use the option std::<algorithm>_if_not or lambda. But for the sake of scientists, I want to know if this is possible:

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

Without writing my own function object, how to make this code work?

+6
source share
3 answers

Remember that the right way to pass char character classification functions (along with toupper and tolower ) that came from the C standard library is to convert it to unsigned char , and then to int .

Using std::ref and a reference_wrapper for this is easy and wrong. Using std::function<bool(int)> or std::function<bool(char)> more difficult as well as incorrect. In all these cases, the char in the string is directly converted to int , which is not suitable for this.

If you insist on not using lambda, then

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

is one right way to do this. Otherwise

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

easier to understand - and shorter.

+8
source

The unary predicate type must determine the type of the member, argument_type , which can be converted to the type of the predicate parameter.

The easiest way to wrap ::ispunct is to use std::reference_wrapper :

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

One approach is to use std::reference_wrapper . Here is a demo program

 #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; } 

Output signal

 h 
-1
source

Source: https://habr.com/ru/post/984205/


All Articles