Russian Qt Forum

Qt => Общие вопросы => Тема начата: Alp от Август 28, 2009, 12:57



Название: QVector и std::for_each
Отправлено: Alp от Август 28, 2009, 12:57
На вызове for_each приложение валится. Значит ли это, что QVector не до конца-таки совместим со стандартными алгоритмами? Можно ли как-нибудь победить эту проблему? Очень уж мне нравятся mem_fun и биндеры.

Код
C++ (Qt)
#include <QApplication>
 
#include <QDebug>
#include <QWidget>
#include <QVector>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   QVector<QWidget*> v;
 
   v.push_back(new QWidget());
   v.push_back(new QWidget());
   v.push_back(new QWidget());
   v.push_back(new QWidget());
   v.push_back(new QWidget());
 
   for_each( v.begin(), v.end(),
             std::bind1st( std::mem_fun( &QWidget::setVisible ), 0) );   //AAAAARRRGGHHHHH!
 
   for( int i = 0; i < v.size(); ++i )
   {
       qDebug() << "Item " << i << ", visibility " << v[i]->isVisible();
   }
 
   return a.exec();
}
 


Название: Re: QVector и std::for_each
Отправлено: KADABRA от Август 28, 2009, 13:22
На вызове for_each приложение валится. Значит ли это, что QVector не до конца-таки совместим со стандартными алгоритмами? Можно ли как-нибудь победить эту проблему? Очень уж мне нравятся mem_fun и биндеры.

Код
C++ (Qt)
...
   for_each( v.begin(), v.end(),
             std::bind1st( std::mem_fun( &QWidget::setVisible ), 0) );   //AAAAARRRGGHHHHH!
...
 
Тут, как бы, получается что std::mem_fun( &QWidget::setVisible ) создаёт функтор первым аргументом которого будет адрес объекта, а std::bind1st( std::mem_fun( &QWidget::setVisible ), 0) биндит этот адрес намертво в ноль. Естественно вызывать метод по нулевому адресу объекта не получится.


Название: Re: QVector и std::for_each
Отправлено: KADABRA от Август 28, 2009, 13:24
Кстати, правильный компилятор бы матюкнулся что не может привести const int к указателю на QWidget.
А решение простое - вместо bind1st надо bind2nd использовать.


Название: Re: QVector и std::for_each
Отправлено: Rcus от Август 28, 2009, 13:28
Эм нет, ноль он магический - преобразуется к нулевому указателю даже если представление нулевого указателя отличается от численного нуля.


Название: Re: QVector и std::for_each
Отправлено: KADABRA от Август 28, 2009, 13:30
Эм нет, ноль он магический - преобразуется к нулевому указателю даже если представление нулевого указателя отличается от численного нуля.
Ну у меня студия девятая точно не дала скомпилировать - пришлось писать (QWidget*)0 чтобы повторить ошибку :)


Название: Re: QVector и std::for_each
Отправлено: kuzulis от Август 28, 2009, 13:30
можно примерно так:

Код:
QVector<QWidget*> v;
...
тут заполнили
...
 foreach (QWidget *w, v) {
    ...
    w->setVisible();
    ...
 }

Не ? :)


Название: Re: QVector и std::for_each
Отправлено: BRE от Август 28, 2009, 13:38
Или так (и это не все варианты)  :)
Код
C++ (Qt)
void visible_helper( QWidget *w, bool val )
{
       w->setVisible( val );
}
 
int main(int argc, char *argv[])
{
   ...
   for_each( v.begin(), v.end(),
             std::bind2nd( std::ptr_fun( &visible_helper ), false ) );
 
   ...
}
 


Название: Re: QVector и std::for_each
Отправлено: Winstrol от Август 28, 2009, 14:01
И, наконец, самый правильный вариант

boost::bind(&QWidget::setVisible,_1,false)

А в варианте приведением к 0 указателю компилятор не прав, да.


Название: Re: QVector и std::for_each
Отправлено: BRE от Август 28, 2009, 14:07
И, наконец, самый правильный вариант

boost::bind(&QWidget::setVisible,_1,false)

А в варианте приведением к 0 указателю компилятор не прав, да.
С boost'ом оно завсегда лучше.  ;D


Название: Re: QVector и std::for_each
Отправлено: Alp от Август 28, 2009, 15:00
Да, действительно, в своем же коде откуда копировал проглядел, что биндится второй параметр.
За варианты спасибо, про прочие фор-ичи я в курсе, буст не использую тут по религиозным соображениям.


Название: Re: QVector и std::for_each
Отправлено: Winstrol от Август 28, 2009, 15:17
буст не использую тут по религиозным соображениям.
А отчего так?
Можно еще как-то так выкрутиться std::tr1::bind