user4708537
user4708537

Reputation: 73

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

Currently if you want to negate a predicate, you have to use a std::<algorithm>_if_not variant or a lambda. But for the sake of academics 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?

Upvotes: 7

Views: 3546

Answers (3)

T.C.
T.C.

Reputation: 137425

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

Using std::ref and a reference_wrapper for this is lightweight, and wrong. Using std::function<bool(int)> or std::function<bool(char)> are more heavyweight, and also wrong. In all those cases the char in the string is directly converted to int, which is not the right way to do it.

If you insist on not using a lambda, then

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

is one right way to do it. Otherwise

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

is easier to understand - and shorter.

Upvotes: 10

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

One of approaches is to use std::reference_wrapper . Here is a demonstrative 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;
}

The output is

h

Upvotes: -1

ecatmur
ecatmur

Reputation: 157454

The unary predicate type must define a member type, argument_type, that is convertible to the predicate's parameter type.

The most lightweight way to wrap ::ispunct is to use std::reference_wrapper:

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

Upvotes: 4

Related Questions