Russian Qt Forum
Июль 22, 2024, 14:12 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: 1 ... 3 4 [5] 6   Вниз
  Печать  
Автор Тема: Итераторы  (Прочитано 31186 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #60 : Апрель 22, 2021, 07:02 »

Там в целом были какие-то изменения в с++11, но яхз, поправлено это или "везет" что все новые компиляторы печатают одинаково.
Конечно поправили, gcc до 7 генерировал неправильный код.
В случае с стримами порядок вызовов функций четко определен.

Код
C++ (Qt)
std::cout << a() << b() << c() << std::endl;
 

Если в b() генерируется исключение, то в потоке должен остаться результат от a(). А теперь посмотрите что кодогенерит gcc до 7. Улыбающийся
« Последнее редактирование: Апрель 22, 2021, 08:58 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #61 : Апрель 22, 2021, 07:19 »

Надеюсь "волна" прошла и можно поговорить о другом. Для удобства повторю часть стартового поста
Есть большой класс, и в нем
Код
C++ (Qt)
struct CBigClass {
...
QList<CData> mData;
QSet<CData *> mSelection;
...
};
А насколько вообще хорош (правомерен и.т.п.) такой выбор контейнеров?

Увы, подозреваю что словоохотливость сразу упадет до нуля. Ну конечно "надо знать задачу" (дежурная отмазка). Да задача самая банальная и которая есть у всех. Есть объекты, они рисуются в окнах и их список предъявляется юзеру (QTreeWidget), конечно их можно выбирать, добавлять, удалять, редактировать. CData - обычный себе объект, не маленький но и не большой.

Единственная специфика - их может быть неприятно много (порядка 100К и больше), поэтому простецкий selectItem не катит в UI. 

So ?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #62 : Апрель 22, 2021, 07:28 »

А насколько вообще хорош (правомерен и.т.п.) такой выбор контейнеров?
Он великолепен. Улыбающийся

Основная ваша проблема в этом:
(как и делать из тела метод)
Как только вы сделаете отдельный метод, все у вас начнет получаться. Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #63 : Апрель 22, 2021, 10:55 »

Если в b() генерируется исключение, то в потоке должен остаться результат от a(). А теперь посмотрите что кодогенерит gcc до 7. Улыбающийся

Ну да, но это с с++11, на тот момент задача была валидная. Я таки носили простыню про sequencing, пункт 19 https://en.cppreference.com/w/cpp/language/eval_order
Но надо понимать что это поправили только для operator<< и >>, для operator+ порядок по-прежнему не задан.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #64 : Апрель 22, 2021, 11:02 »


So ?

Код:
void doWork(const CData &data)
{
}

template<typename С>
void iterateContainer(const С& c)
{
    for (const auto &item: c)
    {
        if constexpr (std::is_pointer_v<C::value_type>)
            doWork(*item);
        else
            doWork(item);
    }
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #65 : Апрель 22, 2021, 11:21 »

Код:
..
}
Про выделение метода сказано в стартовом посте - это не всегда удобно. Но сейчас речь уже не об этом, я спрашиваю удачно ли я выбрал контейнеры вообще (см предыдущий пост). Как буржуи гоаорят
Цитировать
Can you read, or only write?
Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #66 : Апрель 22, 2021, 11:26 »

с 50% вероятностью ответ нет
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #67 : Апрель 23, 2021, 08:44 »

с 50% вероятностью ответ нет
Не думаю здесь есть какие-то "варианты зависящие от задачи". Напр "в вдруг требуется пулеметная вставка/удаление?". Да, так бывает, но вряд ли такой контейнер дается юзверю в UI. А так надо лишь позаботиться чтобы multiply вставки/удаления выполнялись за один проход.

Или популярная байка "std::vector лучше"  (чем QList). В данном случае не вижу чем. "Нормальные" объекты в (подавляющем) большинстве случаев должны быть неперемещаемы. Замена QList<CData> на std::vector<CData *> дает немного больше возможностей, но заметно напрягает с удалением

Рекомендация выше юзать ссылку (вместо указателя). Обычно я охотно это делаю, но в данном случае это "создает впечатление владения", а selection ну вот никак не владеет. Некоторый минус - QSet жрет многовато памяти при обильном selection.

Что же нового/современного можно использовать? (вместо структур > 10 летней давности). Конечно "с выгодой", а не так, абы накрутить. Выходит что здесь и ничего. Или может задача "ну совсем уж серая, банальная", для нее и старого хватит? Или как?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #68 : Апрель 23, 2021, 09:18 »

Что же нового/современного можно использовать? (вместо структур > 10 летней давности).
Для того, что бы появились новые структуры данных, эти новые структуры сначала должен кто-то придумать.
Т.к. от std-шников ждать ничего не приходится, то остаетесь только вы. Улыбающийся
А как придумаете, то std-шники сразу эти новые структуры реализуют в своем убогом std. Улыбающийся
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #69 : Апрель 23, 2021, 11:20 »

Что же нового/современного можно использовать? (вместо структур > 10 летней давности). Конечно "с выгодой", а не так, абы накрутить. Выходит что здесь и ничего. Или может задача "ну совсем уж серая, банальная", для нее и старого хватит? Или как?

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

for (auto& item: mData)
  processItem(item);

и

for (auto* item: mSelection)
  processItem(*item);

И всю обработку столкать в void processItem(CData& item).
Если надо, processItem к тому же можно сделать виртуальной, чтобы в возможных наследниках можно было бы (теоретичски) менять поведение.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« Ответ #70 : Апрель 23, 2021, 11:26 »

Цитировать
Рекомендация выше юзать ссылку (вместо указателя). Обычно я охотно это делаю, но в данном случае это "создает впечатление владения", а selection ну вот никак не владеет. Некоторый минус - QSet жрет многовато памяти при обильном selection.
В этом правда есть.

Изложу лишь следущее: если бы selection был владеющий отдельной копией объекта, т.е. QSet<CData> (не CData*) - это как-то принципиально сломало бы ваш код? Предположу, что нет. Указатель вы используете для уменьшения потребления памяти, ну и бонусом хэш-функция уже есть. Т.е. использование в selection указателей или самих данных определяется их размером, что, согласитесь, семантически ничтожный аргумент. Поэтому ссылка в данном случае - это эффективное владение.

Я допускаю, что выбор указателя может быть как-то связан с хэшированием, например CData неуникальны. Или для них нетривиально придумать хорушую хэш функцию. 

Ваш код был бы проще, если бы было единообразие, которое позволило бы единую обработку шаблонной функцией без is_pointer:
Код:
struct CBigClass {
...
 QList<CData*> mData;
 QSet<CData *> mSelection;
...
}

или

struct CBigClass {
...
 QList<CData> mData;
 QSet<reference_wrapper<CData>> mSelection;
...
};

Порядок таков, что если CData - это класс-сущность (identity class), то используются указатели, если класс данных - то сами классы.

Цитировать
Не думаю здесь есть какие-то "варианты зависящие от задачи"
От специфики задачи зависит, порой, все  Улыбающийся Если у вас часто случаются пулеметные вставки, может рассмотреть вариант сперва сформировать вставку в виде вектора, а потом вставить ее в контейнер как единое целой, т.е. никаких multiply вставок?

Цитировать
Или популярная байка "std::vector лучше"  (чем QList).
Ну как байка? Например, в QList не засунешь std::unique_ptr, а std::unique_ptr в контейнере - это сплошь и рядом. Да, вы можете засунуть std::shared_ptr/QSharedPointer - но это другая (более широкая) семантика, да и код будет менее эффективным.

Например, QList нет еmplace, а еmplace, в свою очередь, может оказаться решающим доводом в пользу типа данных контейнера, соот-но QList дает меньшую свободу.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #71 : Апрель 23, 2021, 15:05 »

И всю обработку столкать в void processItem(CData& item).
Такой processItem может потребовать пяток-десяток доп аргументов что вычисляются в caller'e до цикла

Вот вообще не понимаю проблемы, если честно.
Нет какой-то "большой проблемы", просто хочется писать удобнее/приятнее, это нормально. Напр хорошо бы так
Код
C++ (Qt)
auto & dst = useSelection ? mSelection : mData;
for (auto & data : dst) {
..
}
 
А вместо этого тело выделяй, темплейты заряжай, еще и "сбоку бантик" в виде is_pointer. Где же хваленая гибкость итераторов?

Ваш код был бы проще, если бы было единообразие, которое позволило бы единую обработку шаблонной функцией без is_pointer:
Конечно, проблему стартового поста это решает. Но какой ценой, не получу ли др минусы? Напр первый вариант (оба эл-та указатели) перекладывает работу (во всяком случае часть) на внимательность программиста - в одном контейнере erase должен сопровождаться удалением, в др нет. С враппером выглядит заманчиво, но пока не пробовал, не знаю что там может полезет.

Цитата: AkonResumed link=topic=32938.msg244746#msg244746
Например, в QList не засунешь std::unique_ptr ..
...
Например, QList нет еmplace ...
Да, есть новые вкусные плюшки  Улыбающийся Но нужны ли они для данных стартового поста? Это стандартная задача "предяъвить список объектов", не ошибусь если скажу что ее делал каждый присутствующий. Что станет лучше от использования "новых" средств и каких ?
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #72 : Апрель 23, 2021, 15:09 »

А что мешает тогда создать временный вектор поинтеров на mData? Это всего-то 2 строчки кода..

QList<CData*> dataList;
for (auto& data: mData) dataList << &data;

ну и дальше где нужно выбирать:

auto & dst = useSelection ? mSelection : dataList;
for (auto & data : dst) {
 ..
}
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #73 : Апрель 23, 2021, 15:11 »

..что мешает тогда создать временный вектор ..
Угрызения совести Улыбающийся Все-таки это говнокод
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #74 : Апрель 23, 2021, 15:21 »

Угрызения совести Улыбающийся Все-таки это говнокод

Я на это смотрю и думаю: Да, этому парню говнокод не предложишь.

Код
C++ (Qt)
void CBigClass::SomeMethod( bool useSelection )
{
 ..
 int limit = useSelection ? mSelection.size() : mData.size();
 auto dataIt = mData.begin();  
 auto selIt = mSelection.begin();  
 for (int i = 0; i < limit; ++i) {
   CData * dataPtr;
   if (useSelection) {
      dataPtr = *selIt;
      ++selIt;
   }
   else {
      dataPtr = &(*dataIt);
      ++dataIt;
   }
 
  ...
 }
}
 
Записан
Страниц: 1 ... 3 4 [5] 6   Вверх
  Печать  
 
Перейти в:  


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