Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
537 views
in Technique[技术] by (71.8m points)

stl - How to negate a predicate function using operator ! in C++?

I want to erase all the elements that do not satisfy a criterion. For example: delete all the characters in a string that are not digit. My solution using boost::is_digit worked well.

struct my_is_digit {
 bool operator()( char c ) const {
  return c >= '0' && c <= '9';
 }
};

int main() {
 string s( "1a2b3c4d" );
 s.erase( remove_if( s.begin(), s.end(), !boost::is_digit() ), s.end() );
 s.erase( remove_if( s.begin(), s.end(), !my_is_digit() ), s.end() );
 cout << s << endl; 
 return 0;
}

Then I tried my own version, the compiler complained :( error C2675: unary '!' : 'my_is_digit' does not define this operator or a conversion to a type acceptable to the predefined operator

I could use not1() adapter, however I still think the operator ! is more meaningful in my current context. How could I implement such a ! like boost::is_digit() ? Any idea?

Update

Follow Charles Bailey's instruction, I got this code snippet compiled, however the output is nothing:

struct my_is_digit : std::unary_function<bool, char> {
    bool operator()( char c ) const {
        return isdigit( c );
    }
};

std::unary_negate<my_is_digit> operator !( const my_is_digit& rhs ) {
    return std::not1( rhs );
}

int main() {
    string s( "1a2b3c4d" );
    //s.erase( remove_if( s.begin(), s.end(), !boost::is_digit() ), s.end() );
    s.erase( remove_if( s.begin(), s.end(), !my_is_digit() ), s.end() );
    cout << s << endl;  
    return 0;
}

Any idea what was wrong?

Thanks,
Chan

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You should be able to use std::not1.

std::unary_negate<my_is_digit> operator!( const my_is_digit& x )
{
    return std::not1( x );
}

For this to work you have to #include <functional> and derive your my_is_digit functor from the utility class std::unary_function< char, bool >. This is purely a typedef helper and adds no runtime overhead to your functor.


Complete working example:

#include <string>
#include <algorithm>
#include <functional>
#include <iostream>
#include <ostream>

struct my_is_digit : std::unary_function<char, bool>
{
    bool operator()(char c) const
    {
        return c >= '0' && c <= '9';
    }
};

std::unary_negate<my_is_digit> operator!( const my_is_digit& x )
{
    return std::not1( x );
}

int main() {
    std::string s( "1a2b3c4d" );
    s.erase( std::remove_if( s.begin(), s.end(), !my_is_digit() ), s.end() );
    std::cout << s << std::endl;
    return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...