Russian Qt Forum
Ноябрь 24, 2024, 23:25 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: qSort: метод класса в качестве функции сравнения...  (Прочитано 8064 раз)
Cyrax
Гость
« : Январь 06, 2008, 14:19 »

Может, это и C++, но вопрос такой:
Имеется класс  Manager c методом compareIdsByNum_lessThan, сравнивающим 2 целых числа (идентификатора) на основе информации из объекта этого класса (т.е. сравнение происходит с учётов некоторых характеристик этих идентификаторов, а не просто "сравнить 2 числа"):
Цитировать
bool compareIdsByNum_lessThan(const int &id_1, const int &id_2);
В одном из методов класса Manager сортирую элементы списка (целые числа - идентификаторы) функцией qSort. parameterEndUse_index - список QList этих идентификаторов (целых чисел).

Цитировать
qSort(this->parameterEndUse_index.begin(), this->parameterEndUse_index.end(), Manager::compareIdsByNum_lessThan);
Результат:
Цитировать
argument of type `bool (Manager:Улыбающийся(const int&, const int&)' does not match `bool (Manager::*)(const int&, const int&)'

Ставим "указатель" на метод класса:
Цитировать
qSort(this->parameterEndUse_index.begin(),
        this->parameterEndUse_index.end(),
        &Manager::compareIdsByNum_lessThan);
Результат:
Цитировать
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h   instantiated from `void qSort(RandomAccessIterator, RandomAccessIterator, LessThan) [with RandomAccessIterator = QList<int>::iterator, LessThan = bool (Manager::*)(const int&, const int&)]'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'

Одна и та же ошибка аж в 6 экземплярах...

Делаем то же самое через предварительно объявленный и проинициализированный указатель на метод:

bool (Manager::*lessThan)(const int &id_1, const int &id_2);
lessThan = &Manager::compareIdsByNum_lessThan;
qSort(this->parameterEndUse_index.begin(),
        this->parameterEndUse_index.end(),
        lessThan);

Результат - тот же:
Цитировать
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h   instantiated from `void qSort(RandomAccessIterator, RandomAccessIterator, LessThan) [with RandomAccessIterator = QList<int>::iterator, LessThan = bool (Manager::*)(const int&, const int&)]'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'
c:/GPL/Qt/4.3.1/include/QtCore/../../src/corelib/tools/qalgorithms.h must use .* or ->* to call pointer-to-member function in `lessThan (...)'

Что за чудеса ?
« Последнее редактирование: Январь 06, 2008, 14:23 от Cyrax » Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #1 : Январь 06, 2008, 15:30 »

Вынеси метод compareIdsByNum_lessThan из класса Manager или попробуй объявить её как static
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Cyrax
Гость
« Ответ #2 : Январь 06, 2008, 16:51 »

Цитировать
Вынеси метод compareIdsByNum_lessThan из класса Manager или попробуй объявить её как static
Ни то, ни другое не получится, т.к. метод compareIdsByNum_lessThan при сравнении использует информацию, которую содержит объект класса Manager...
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #3 : Январь 06, 2008, 18:29 »

Со static работает 100 процентов, при условии что нет ображения к нестатическим данным класса.

По теме: имхо, так сделать не получиться (см. исходники qSortHelper).

Вызов метода сравнения элементов не заточен для работы с методами класса или указателями на них.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Cyrax
Гость
« Ответ #4 : Январь 06, 2008, 21:34 »

A STL-кий sort сработает ?
Записан
Cyrax
Гость
« Ответ #5 : Январь 12, 2008, 13:25 »

Цитировать
Вызов метода сравнения элементов не заточен для работы с методами класса или указателями на них.
Не то, чтобы не заточен. Просто в случае передачи нестатического метода какого-либо объекта qSort'у по-любому придётся передать ещё один параметр - объект, из которого следует вызывать метод...

Собственно, STL'кий sort должен реагировать на такие попыткаи аналогичным образом...
Записан
Вячеслав
Гость
« Ответ #6 : Январь 12, 2008, 23:09 »

Я тут недавно рассматривал штуку http://www.codeproject.com/KB/cpp/FastDelegate.aspx 
вот кусок демки
Код:
    printf("-- FastDelegate demo --\nA no-parameter 
             delegate is declared using FastDelegate0\n\n");             
           
    FastDelegate0 noparameterdelegate(&SimpleVoidFunction);

    noparameterdelegate();
    // invoke the delegate - this calls SimpleVoidFunction()


    printf("\n-- Examples using two-parameter delegates (int, char *) --\n\n");

    typedef FastDelegate2<int, char *> MyDelegate;

    MyDelegate funclist[10]; // delegates are initialized to empty

    CBaseClass a("Base A");
    CBaseClass b("Base B");
    CDerivedClass d;
    CDerivedClass c;
   
  // Binding a simple member function

    funclist[0].bind(&a, &CBaseClass::SimpleMemberFunction);
  // You can also bind static (free) functions

    funclist[1].bind(&SimpleStaticFunction);
  // and static member functions

    funclist[2].bind(&CBaseClass::StaticMemberFunction);
  // and const member functions

    funclist[3].bind(&a, &CBaseClass::ConstMemberFunction);
  // and virtual member functions.

    funclist[4].bind(&b, &CBaseClass::SimpleVirtualFunction);

  // You can also use the = operator. For static functions,

  // a fastdelegate looks identical to a simple function pointer.

    funclist[5] = &CBaseClass::StaticMemberFunction;

  // The weird rule about the class of derived

  // member function pointers is avoided.

  // Note that as well as .bind(), you can also use the

  // MakeDelegate() global function.

    funclist[6] = MakeDelegate(&d, &CBaseClass::SimpleVirtualFunction);

  // The worst case is an abstract virtual function of a

  // virtually-derived class with at least one non-virtual base class.

  // This is a VERY obscure situation, which you're unlikely to encounter

  // in the real world, but it's included as an extreme test.

    funclist[7].bind(&c, &CDerivedClass::TrickyVirtualFunction);
  // ...BUT in such cases you should be using the base class as an

  // interface, anyway. The next line calls exactly the same function.

    funclist[8].bind(&c, &COtherClass::TrickyVirtualFunction);

  // You can also bind directly using the constructor

    MyDelegate dg(&b, &CBaseClass::SimpleVirtualFunction);

    char *msg = "Looking for equal delegate";
    for (int i=0; i<10; i++) {
        printf("%d :", i);
        // The ==, !=, <=,<,>, and >= operators are provided

        // Note that they work even for inline functions.

        if (funclist[i]==dg) { msg = "Found equal delegate"; };
        // There are several ways to test for an empty delegate

        // You can use if (funclist[i])

        // or          if (!funclist.empty())

        // or          if (funclist[i]!=0)

        // or          if (!!funclist[i])

        if (funclist[i]) {
            // Invocation generates optimal assembly code.

            funclist[i](i, msg);
        } else {
            printf("Delegate is empty\n");
        };
    }

Как видно жрет и статики и обычные методы Подмигивающий Вроде и boost::bind совместима ..... Не пойдет как вариант ?
Записан
Cyrax
Гость
« Ответ #7 : Январь 12, 2008, 23:58 »

Спасибо, но я уже свой сортировщик написал.
Разбираться сейчас - время жалко..
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.28 секунд. Запросов: 23.