Как отменить предикатную функцию, используя оператор! в С ++? - PullRequest
4 голосов
/ 03 января 2011

Я хочу стереть все элементы, которые не удовлетворяют критерию.Например: удалите все символы в строке, которые не являются цифрами.Мое решение с использованием boost :: is_digit работало хорошо.

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

Затем я попробовал свою собственную версию, компилятор пожаловался :( ошибка C2675: унарный '!': 'My_is_digit' не определяет этот оператор или преобразованиек типу, приемлемому для предопределенного оператора

Я мог бы использовать адаптер not1 (), однако я все еще думаю, что оператор! является более значимым в моем текущем контексте. Как я могу реализовать такой! like boost :: is_digit ()? Есть идеи?

Обновление

Следуя инструкциям Чарльза Бэйли, я получил отрывок кода, однако на выходе ничего нет:

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

Любая идея, что случилось?

Спасибо,
Чан

Ответы [ 2 ]

11 голосов
/ 03 января 2011

Вы должны быть в состоянии использовать std::not1.

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

Чтобы это работало, вам нужно #include <functional> и извлечь функтор my_is_digit из класса утилит std::unary_function< char, bool >. Это просто помощник typedef, и он не добавляет накладных расходов на время выполнения функтору.


Полный рабочий пример:

#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;
}
2 голосов
/ 03 января 2011

Как я мог реализовать такое! как boost :: is_digit ()

... возможно, вы могли бы взглянуть на код, который формирует реализацию is_digit? Вы увидите predicate_facade и соответствующий код:

template<typename PredT>
inline detail::pred_notF<PredT>
operator!( const predicate_facade<PredT>& Pred )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_notF<PredT>(*static_cast<const PredT*>(&Pred)); 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...