Функция сравнения для сортировки вектора-члена с помощью sort () - PullRequest
1 голос
/ 30 апреля 2011

у меня есть такой класс:

class test
{  
    vector<expr*> _exprs;  

    bool cmp(expr* e1, expr* e2);   

    ExprManager* mg;  
}  

и функция сравнения:

bool test::cmp(expr* e1, expr* e2)  
{  
    return exprHight(mg, e1) < exprHight(mg, e2);  
}  

тогда, когда я использую функцию сравнения при сортировке _exprs (в другой функции-член)

sort(_exprs->begin(), _exprs->end(), cmp);  

Отчет компилятора:

error: argument of type ‘bool (test::)(void*, void*)’ does not match ‘bool (test::*)(void*, void*)’

Как это исправить?Спасибо за продвижение.

Ответы [ 3 ]

2 голосов
/ 30 апреля 2011

Обычный способ определения предиката для сортировки - это функтор.

Сделайте так, чтобы ваш класс определил operator() для сравнения, и вы можете просто передать экземпляр класса в std::sort.

Так что на самом деле все, что вам нужно сделать, это определить класс следующим образом:

class test
{  
    vector<expr*> _exprs;  

    bool operator()(expr* e1, expr* e2);   

    ExprManager* mg;  
}  

И тогда вы можете позвонить sort так:

sort(_exprs->begin(), _exprs->end(), test());  

или, конечно, использовать существующий экземпляр класса test вместо создания нового. Но вы просто передаете экземпляр класса, и вам вообще не нужно упоминать функцию-член.

Если сортировка выполняется в другой функции-члене (она выглядит так, как вы указали в _exprs), напишите

sort(_exprs->begin(), _exprs->end(), *this);  

Следует отметить, что std::sort, как и большинство других стандартных библиотечных алгоритмов, копирует объект предиката, и поэтому ваш класс предикатов должен иметь возможность безопасно обрабатывать копирование (что ваши классы всегда должны делать в любом случае * 1023) *)

Короче говоря, способ достичь этого - следовать «правилу трех».

Если ваш класс определяет деструктор, конструктор копирования или оператор присваивания, то он почти наверняка определит все три.

Если используется созданный компилятором конструктор копирования, он просто скопирует члены-указатели вашего класса, поэтому у вас будет два объекта, содержащих указатели на один и тот же объект.

Если в классе есть деструктор, который вызывает delete для этого указателя, то это заканчивается дважды. Что является ошибкой.

Если ваш класс предназначен для копирования (а большая часть стандартной библиотеки требует этого), то вы должны определить соответствующие конструкторы копирования и операторы присваивания для его безопасной реализации (например, скопировать ресурс, на который указывает указатель, или вместо этого используйте умный указатель).

Если ваш класс не предназначен для копирования, то вы должны определить конструктор копирования и операторы присваивания как private, так что попытки скопировать класс приведут к ошибке во время компиляции вместо сбоев во время выполнения.

Вы должны никогда определять класс, который можно копировать, но он делает это неправильно. Либо определите необходимый конструктор копирования / оператор / деструктор присваивания для обработки копирования, либо сделайте копирование невозможным, сделав копирование ctor / оператора присваивания частным.

Обертывание указателей в динамически распределенную память, принадлежащую классу, в интеллектуальных указателях - это простой способ получить бесплатное копирование.

Если класс содержит только объекты RAII, вам вообще не нужно определять деструктор, и поэтому правило трех не требует, чтобы вы также определяли конструктор копирования и оператор присваивания.

1 голос
/ 30 апреля 2011

Вам нужно сделать test::cmp() статическим :

class test {
    // ...
    static bool cmp( expr * lhs, expr * rhs );
};

В качестве альтернативы, если test::cmp() не может быть статическим по какой-то причине, вам необходимо использовать(boost:: или std::tr1::) bind() для привязки (неявного) this параметра cmp():

test * someInstance = this // other // something;
sort( _exprs->begin(), _exprs->end(),
      bind( &test::cmp,  someInstance, _1, _2 ) );
0 голосов
/ 30 апреля 2011

Используйте operator (), а затем передайте '* this' в качестве алгоритма Predicate to Sort.

class test
{  
    vector<expr*> _exprs;  

    bool operator()(expr* e1, expr* e2);   

    ExprManager* mg;  
}  

sort(_exprs->begin(), _exprs->end(), *this);  

Все, что вы передаете в качестве предиката, должно быть общедоступным,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...