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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QVector и std::for_each  (Прочитано 6688 раз)
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();
}
 
Записан
KADABRA
Гость
« Ответ #1 : Август 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) биндит этот адрес намертво в ноль. Естественно вызывать метод по нулевому адресу объекта не получится.
Записан
KADABRA
Гость
« Ответ #2 : Август 28, 2009, 13:24 »

Кстати, правильный компилятор бы матюкнулся что не может привести const int к указателю на QWidget.
А решение простое - вместо bind1st надо bind2nd использовать.
Записан
Rcus
Гость
« Ответ #3 : Август 28, 2009, 13:28 »

Эм нет, ноль он магический - преобразуется к нулевому указателю даже если представление нулевого указателя отличается от численного нуля.
Записан
KADABRA
Гость
« Ответ #4 : Август 28, 2009, 13:30 »

Эм нет, ноль он магический - преобразуется к нулевому указателю даже если представление нулевого указателя отличается от численного нуля.
Ну у меня студия девятая точно не дала скомпилировать - пришлось писать (QWidget*)0 чтобы повторить ошибку Улыбающийся
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #5 : Август 28, 2009, 13:30 »

можно примерно так:

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

Не ? Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #6 : Август 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 ) );
 
   ...
}
 
Записан
Winstrol
Гость
« Ответ #7 : Август 28, 2009, 14:01 »

И, наконец, самый правильный вариант

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

А в варианте приведением к 0 указателю компилятор не прав, да.
Записан
BRE
Гость
« Ответ #8 : Август 28, 2009, 14:07 »

И, наконец, самый правильный вариант

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

А в варианте приведением к 0 указателю компилятор не прав, да.
С boost'ом оно завсегда лучше.  Смеющийся
Записан
Alp
Гость
« Ответ #9 : Август 28, 2009, 15:00 »

Да, действительно, в своем же коде откуда копировал проглядел, что биндится второй параметр.
За варианты спасибо, про прочие фор-ичи я в курсе, буст не использую тут по религиозным соображениям.
Записан
Winstrol
Гость
« Ответ #10 : Август 28, 2009, 15:17 »

буст не использую тут по религиозным соображениям.
А отчего так?
Можно еще как-то так выкрутиться std::tr1::bind
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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