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

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

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

Сообщений: 11445


Просмотр профиля
« Ответ #15 : Июль 22, 2014, 17:19 »

ну findfirst/findnext в крайнем случае, а это вы хрень какую-то написали. Улыбающийся
Не стоит резво судить о нативном коде платформы на которой никогда не работали  Улыбающийся

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

Сообщений: 4349



Просмотр профиля
« Ответ #16 : Июль 22, 2014, 17:33 »

Не стоит резво судить о нативном коде платформы на которой никогда не работали  Улыбающийся
А я резко и не сужу, там под капотом unix, а это значит opendir в нативе, а не эта высокоуровневые хрень, что вы привели. Понимаю, что вы такого натива не знаете.

Именно - даже под дулом автомата Вы не вернетесь у нативному коду.
Ерунда. Если понадобиться, то с удовольствием вернусь. Только я сделаю удобные классы, куда и спрячу весь натив, а не буду везде писать этот фарш.
Кстати, Армы сейчас к этому сильно располагают.

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

Сообщений: 4724



Просмотр профиля WWW
« Ответ #17 : Июль 22, 2014, 18:16 »

2Igors: на Objective-C с его фреймворками пишется проще
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Июль 22, 2014, 18:43 »

Ерунда. Если понадобиться, то с удовольствием вернусь. Только я сделаю удобные классы, куда и спрячу весь натив, а не буду везде писать этот фарш.
Последние полгода активно избавляюсь от от таких удобных классов, так что про удовольствие не заливайте  Улыбающийся

2Igors: на Objective-C с его фреймворками пишется проще
Да, Objective придется изучать и по многим др причинам.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #19 : Июль 22, 2014, 19:15 »

Последние полгода активно избавляюсь от от таких удобных классов, так что про удовольствие не заливайте  Улыбающийся
Значит они у вас были такие "удобные". Улыбающийся
Страшно представить, что там у вас было, если вы на это переходите и радуетесь этому:
Код
C++ (Qt)
FSIterator iterator;
OSStatus error = FSOpenIterator(&ref, kFSIterateFlat, &iterator);
if (error) return false;
 
ItemCount maxCount = 10;
FSSpec FS[10];
 
while (true) {
error = FSGetCatalogInfoBulk(
iterator,
10, // ItemCount maximumObjects,
&maxCount, // ItemCount * actualObjects,
0, // Boolean * containerChanged,
kFSCatInfoNone, // FSCatalogInfoBitmap whichInfo,
0, // FSCatalogInfo * catalogInfos,
0, // FSRef * refs,
FS, // FSSpec * specs,
0 // HFSUniStr255 * names
);
if (error && error != errFSNoMoreItems) break;
Boolean aliasFileFlag, folderFlag;
 
for (int i = 0; i < maxCount; ++i) {
 OSErr err2 = IsAliasFile(FS + i, &aliasFileFlag, &folderFlag);
...

Надеюсь никому не придется это переделывать в будущем. Подмигивающий
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #20 : Июль 22, 2014, 23:40 »

Ну второй как-то "не сильно хуже" и, на мой взгляд, гибче. Понадобится напр обновлять индикатор и/или проверить отмену (юзверь нажал cancel) - и как это встроить в std::copy?

Не очень понятно о чем речь. Но если я правильно понял, то вы можете использовать предикат.
http://www.cplusplus.com/reference/algorithm/copy_if/

А при незатейливом цикле этой проблемы нет.

Итераторы позволяют итерироваться универсально. Без итераторов - получаем зоопарк "конкретных случаев".
Это имеет кучу минусов. Я бы сказал - фатальных минусов. Серьезное переусложнение.

Вообще короткий, элегантный текст обоих примеров достигнут за счет использования мощностей буста, силу итераторов он не демонстрирует  Улыбающийся

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

Кстати:

Код:
...
some obj;
...
for(const auto& i: obj)
    cout<<i<<endl;

Незатейливый цикл реализуется за счет begin()/end() методов объекта любого типа, которые возвращают итераторы.
То есть, если реализовать итераторы для вашего кастомного механизма, то данный вид цикла сможет с ним работать.

Одной из разновидностей таких "кастомных" механизмов являются так называемые "вариативные типы данных".


Пример вариативного механизма:

    
Код:
   // в качестве значения можно посетить практически все что угодно
    Var v1;
    v1["hello"] = 10;
    v1["text"]  = "eos";
    v1["world"] = true;

    Var v;
    v["one"] = 10.5;
    v["two"] = v1;
    v["bar"] = "message";
    
    cout<<  v.ToHummanStyle()<<endl;
Цитировать
       map:
          'bar' "message"
          'one' 10.5
          'two' map:
            'hello' 10
            'text' "eos"
            'world' true


Вариативные типы данных позволяют пичкать их как простыми значениями разных типов, так и массивами, векторами, мапами, и тд и тп.

Теперь представьте себе: на входе вы получаете какой нибудь Variant, который содержит внутри себя нехилую такую древовидную структуру всяческих чевотов.

И как вы себе представляете обход такого дерева без итераторов?

С итераторами все просто:
Нет принципиальной разницы: обходить дерево файловой системы, встречая по пути папки (контейнерные типы), или файлы (примитивные типы-значения).

Разные контейнерные типы - да не проблема. Итераторам все равно пофигу как по ним по всем бегать.
Поэтому, вариативный тип без каких либо изменений или доработок уже поддерживает любые типы контейнеров, если они умеют стандартизированные итераторы.

Без итераторов задача стала бы очень нетривиальной - пришлось бы пасти все возможные случаи, и каждый такой случай обрабатывать отдельно.

получился бы километр кода в самом механизме. И километр кода на стороне пользователя.
При этом, если захочется добавить поддержку ещё какого нибудь нового контейнера - пришлось бы вручную дописывать код.
И это - вместо простого и элегантного решения всего в несколько строк.
« Последнее редактирование: Июль 22, 2014, 23:45 от _Bers » Записан
Bepec
Гость
« Ответ #21 : Июль 22, 2014, 23:58 »

А если сократить предыдущего оратора:
Итератор это объект, абстрагирующий за единым интерфейсом доступ к элементам коллекции.

Он не силён, он не могуч. Он обеспечивает доступ и не более.

А вот обрабатывать каждый случай будет не он, а следующий аз ним код Улыбающийся

PS все слова о сокращении кода - муть. Там будет тот же код, только спрятанный в классе Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #22 : Июль 23, 2014, 00:29 »

А вот обрабатывать каждый случай будет не он, а следующий аз ним код Улыбающийся

PS все слова о сокращении кода - муть. Там будет тот же код, только спрятанный в классе Улыбающийся

Чушь..( Не надо вводить людей в заблуждения подобными заявлениями.

Похоже вы так и не поняли о чём хотел сказать _Bers.. И не только он..
Но всё бестолку..(




Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #23 : Июль 23, 2014, 00:37 »

PS все слова о сокращении кода - муть. Там будет тот же код, только спрятанный в классе Улыбающийся

Код перебора элементов контейнера уже написан, и содержится в самих контейнерах.

Приведу пример:

Предположим, что есть некий универсальный тип данных, которые умеет принимать любые примитивные типы: int/float/etc

Код:
Value v1=10;
Value v2=10.5f;
Value v3=true;

Теперь:

Я делаю:

Код:
::std::vector<Value> myvec;

Поскольку, сам Value умеет работать с любыми прититивами, то я только что создал вектор "любых примитивов"

Код:
myvec.emplace_back(10);
myvec.emplace_back(true);

Теперь представьте себе, что Value умеет принимать не только "тип-значение", а вообще объекты любых типов.
наподобие boost::any

В этом случае ему станет возможным подсунуть контейнер "любых примитивов" :

Код:
Value val = myvec;
В точки присвоения объекта вариативному типу, отрабатывает шаблоно-конструкция, в который времени компиляции можно "детектить" наличие в типе методов begin/end

Так Value можно научить дергать контейнеры за итераторы, если они вообще есть.

Получаем: вариативный механизм, который не содержит ни строчки кода о том, как нужно перебирать контейнеры.
Весь этот код уже написан, и содержится в самих контейнерах, таких, как ::std::vector, или ::std::map

Мы лишь параметризуем эти контейнеры типом Value, и дергаем за их итераторы для перебора.

Теперь переименуем Value в Variant и получаем одну из многих моделей вариативного типа.

И если в какой то момент захочется добавить, например ::std::list, то мы можем сделать просто:

Код:
::std::list<Value> mylist;
Value val = mylist;

И пользоваться. Никаких доработок в самом Value делать не нужно, потому что ::std::list сам прекрасно знает как ему себя итерировать.
Записан
Bepec
Гость
« Ответ #24 : Июль 23, 2014, 10:30 »

Ну собственно это итератор и шаблоны. Вот теперь я действительно не понимаю что вы хотели сказать последним сообщением.

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

Но что будет в случае с контейнером, не поддерживающим итераторы?

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

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Июль 23, 2014, 11:33 »

Ну хорошо, давайте про  "контейнер любых типов". Есть древняя структура (в хвосте поста), менять ее нельзя т.к. она создается внешним редактором. Массив/контейнер таких структур "отображается" в массив существующих UI элементов. Смысл: имея массив структур + UI мы его запускаем без всякого доп кода, крутим пока не нажато Ok/Cancel и сливаем значения в выходную структуру. Таким образом никакого UI кода юзер не пишет. Давным-давно был написан совершенно лобовой код для всего этого, в псевдокоде выглядит так (ну конечно реально там совсем не QWidget - тогда Qt еще не успело родиться)

Код
C++ (Qt)
bool AcceptData( std::vector <CData> & data  )
{
for (size_t i = 0; i  < data.size(); ++i) {
  QWidget * w = GetWidget(i);     // берем UI элемент
  int type = GetWidgetType(w);    
 
// пошли разборки
  switch (type) {
    case edit_Text:
      switch (data[i].rmp_Type) {
        case TYPE_SFLOAT:
            float val = GetFloat(w);
            if (data[i].rmp_Flag & FLAG_BIT_LIMITED) {
               // проверка диапазона
            }
            // запись в выходную структуру
            break;
      }
  }
}
}
 
Затем все повторяется для др типов CData (TYPE_UFLOAT, TYPE_SLONG, TYPE_ULONG, TYPE_BOOLEAN, TYPE_OPTION, TYPE_RGB, TYPE_ARGB). Но это все только для контрола editText. Для всех др контролов - все по новой, т.е. еще ветки case. И это все прием данных из UI. Для их установки - еще код такого же объема. Понятно что надо все это как-то обобщить - но как?

Сама структура
Код
C++ (Qt)
struct CData
{
enum
{
TYPE_UNDEFINED,
TYPE_SFLOAT,
TYPE_UFLOAT,
TYPE_SLONG,
TYPE_ULONG,
TYPE_BOOLEAN,
TYPE_OPTION,
TYPE_RGB,
TYPE_ARGB,
TYPE_CUSTOM
};
 
enum
{
FLAG_BIT_LIMITED = 31,
FLAG_BIT_ANIMATE = 30
};
 
 
unsigned char rmp_Name[32];
long rmp_Flag;
unsigned long rmp_Type;
 
union
{
struct
{
double rmp_Value;
double rmp_Minimum;
double rmp_Maximum;
} valReal;
 
struct
{
long rmp_Value;
long rmp_Minimum;
long rmp_Maximum;
} valLong;
 
struct
{
long rmp_Value;
} valBool;
 
struct
{
long rmp_Value;
short rmp_ResourceID;
} valOption;
 
struct
{
unsigned short rmp_Red;
unsigned short rmp_Green;
unsigned short rmp_Blue;
unsigned short rmp_Alpha;
} valColor;
 
} channelData;
 
CustomData rmp_CustomData;
};
 

2_Bers Рассказываете Вы интересно и понятно, спасибо. Но все-таки "то примеры", а что будет на практике - неясно. Молодые-начитанные хотят по-быстрому чего-то слепить (пуская пыль в глаза теми же итераторами), в дедушкином коде копаться не хотят  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #26 : Июль 23, 2014, 15:58 »

А можно подробней?
Вот мы взяли нулевой элемент вектора data. По индексу взяли виджет, я так понимаю, из ui и спросили его тип - пусть это будет "Текстовая строка".
А дальше мы пытаемся из этой текстовой строки вытащить/установить данные в формате, заданном в элементе структуры CData?
А если виджет QLineEdit, а элемент TYPE_RGB, то нам нужно попробовать из строки виджета получить/установить цвет?

И огласите сразу все возможные типы виджетов.

P.S. И последний вопрос: этот код эту вермишель выше вы писали?  Строит глазки
« Последнее редактирование: Июль 23, 2014, 16:13 от Old » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #27 : Июль 23, 2014, 22:59 »

Igors,мне не понятна идея.

Приходит какой то массив данных.

Берется i-й виджет.

Для него выясняется числовой идентификатор типа.
Выясняется числовой идентификатор типа i-го элемента данных.

Для конкретного числового идентификатора типа виджета и конкретного числового идентификатора элемента данных что-то делается....


Что? Не понятно.. Не понятно почему именно так делается.

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

Кстати:

Код:
switch (data[i].rmp_Type) {
         case TYPE_SFLOAT:
             float val = GetFloat(w);
             if (data[i].rmp_Flag & FLAG_BIT_LIMITED) {
                // проверка диапазона
             }

можно заменить на:

Код:
switch (data[i].rmp_Type) {
         case TYPE_SFLOAT:
             float val = GetFloat(w);
             if (TYPE_SFLOAT & FLAG_BIT_LIMITED) {
                // проверка диапазона
             }

Если я правильно понял нотацию, то FLAG_BIT_LIMITED является константой. Следовательно все выражение:
Код:
TYPE_SFLOAT & FLAG_BIT_LIMITED
Является константой.

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

Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #28 : Июль 23, 2014, 23:29 »

Но что будет в случае с контейнером, не поддерживающим итераторы?

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

Код:
int i = 10;   //<---- не умеет итераторы

Value v = i;  //<--- Value считает, что ему подсунули "не_контейнер"

...

Some obj; //<---- не умеет итераторы
v = obj;  //<--- Value считает, что ему подсунули "не_контейнер"


Вариант может просто хранить примитивы, но он не будет пытаться итерироваться внутри их.
Записан
Bepec
Гость
« Ответ #29 : Июль 24, 2014, 07:17 »

Спасибо за ответ - думал тут уже забыли о вопросе Улыбающийся
Собственно как я и думал.
Записан
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


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