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

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

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

Сообщений: 2130



Просмотр профиля
« : Ноябрь 03, 2015, 11:03 »

Привет, друзья!
В этой теме я представлю шаблон итератора, который пробегается по элементам контейнера из начала в конец.
Идея принадлежит Пантеру, с его же немалой помощью я её реализовал.
Ниже представлен код шаблона:
Код
C++ (Qt)
namespace Impl{
 
template<class ContainerIterator>
class Iterator
{
   using ValueType = typename std::iterator_traits<ContainerIterator>::value_type;
public:
   Iterator(const ContainerIterator& begin, const ContainerIterator& end)
       : begin_(begin),
         end_(end)
       {}
 
   bool atEnd() const{
       return begin_ == end_;
   }
 
   bool hasNext() const{
       return begin_ != end_;
   }
 
   ValueType& operator++(){
       return next();
   }
 
   ValueType operator++() const{
       return next();
   }
 
   ValueType& next(){
       return *(++begin_);
   }
 
   ValueType next() const{
       return *(++begin_);
   }
 
   ValueType& operator*(){
       return *begin_;
   }
 
   ValueType operator*() const{
       return *begin_;
   }
 
private:
   ContainerIterator begin_;
   ContainerIterator end_;
};
 
}
template<class Container>
class Iterator: public Impl::Iterator<typename Container::iterator>{
public:
   explicit Iterator(Container& container)
       : Impl::Iterator<typename Container::iterator>(container.begin(), container.end())
   {
 
   }
 
};
 
template<class Container>
class ConstIterator: public Impl::Iterator<typename Container::const_iterator>{
public:
   explicit ConstIterator(const Container& container)
       : Impl::Iterator<typename Container::const_iterator>(container.begin(), container.end())
   {
 
   }
 
};
 
template<class Container>
auto makeIterator(Container& container) -> Iterator<Container>{
   return Iterator<Container>(container);
}
 
template<class Container>
auto makeIterator(const Container& container) -> ConstIterator<Container>{
   return ConstIterator<Container>(container);
}
 
template<class Container>
auto makeConstIterator(const Container& container) -> ConstIterator<Container>{
   return ConstIterator<Container>(container);
}
 
 
Далее показан пример его использования:
Код
C++ (Qt)
QVector<double> xNodes; // x coordinates array
QVector<double> yNodes; // y coordinates array
QVector<double> zNodes; // z coordinates array
QMatrix3x3 rotMatrix; // rotation matrix
/*......*/
for (auto itX = makeIterator(xNodes), itY = makeIterator(yNodes), itZ = makeIterator(zNodes);
   itX.hasNext() && itY.hasNext() && itZ.hasNext();
   ++itX, ++itY, ++itZ){
   rotateVertex(rotMatrix, *itX, *itY, *itZ);
}
 
« Последнее редактирование: Ноябрь 03, 2015, 11:24 от __Heaven__ » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Ноябрь 03, 2015, 11:07 »

Для создания константного итератора нужно назвать makeConstIterator. Это я не доглядел.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #2 : Ноябрь 03, 2015, 11:15 »

Цитировать
Код
C++ (Qt)
for (auto itX = makeIterator(xNodes), itY = makeIterator(yNodes), itZ = makeIterator(zNodes);
   itX.hasNext() && itY.hasNext() && itZ.hasNext();
   ++itX, ++itY, ++itZ){
   rotateVertex(rotMatrix, *itX, *itY, *itZ);
}
 
А чем это отличается от:
Код
C++ (Qt)
for (auto itX = xNodes.begin(), itY = yNodes.begin(), itZ = zNodes.begin();  itX !=xNodes.end(); ++itX, ++itY, ++itZ)
{
   rotateVertex(rotMatrix, *itX, *itY, *itZ);
}
 
Записан

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

Arch Linux Plasma 5
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #3 : Ноябрь 03, 2015, 11:17 »

m_ax, а если разные размеры у векторов?
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #4 : Ноябрь 03, 2015, 11:20 »

Цитировать
m_ax, а если разные размеры у векторов?
Ну пусть будут разные  Улыбающийся

Код
C++ (Qt)
for (auto itX = xNodes.begin(), itY = yNodes.begin(), itZ = zNodes.begin();  itX !=xNodes.end() && itY != yNodes.end() && itZ != zNodes.end(); ++itX, ++itY, ++itZ)
{
   rotateVertex(rotMatrix, *itX, *itY, *itZ);
}
 
Записан

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

Arch Linux Plasma 5
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #5 : Ноябрь 03, 2015, 11:25 »

Для создания константного итератора нужно назвать makeConstIterator.
Добавил
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #6 : Ноябрь 03, 2015, 11:26 »

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

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #7 : Ноябрь 03, 2015, 11:28 »

m_ax, а это хорошо, что у нас end() вызывается на каждой итерации?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #8 : Ноябрь 03, 2015, 11:29 »

Вызов end() скорее всего компиль соптимизячит и сделает один раз. Но многие советуют все же делать так (auto it = v.begin(), end = v.end(); it != end; ++it)
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Ноябрь 03, 2015, 11:33 »

Код
C++ (Qt)
size_t limit = qMin(qMin(xNodes.size(), yNodes.size()), zNodes.size());
for (size_t i = 0; i < limit; ++i)
   rotateVertex(rotMatrix, xNodes[i], yNodes[i], zNodes[i]);
А если "учится" то давно пора x, y, z иметь как структуру с операторами, а не держать их отдельно в сопливых массивах.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #10 : Ноябрь 03, 2015, 11:34 »

Код
C++ (Qt)
for (auto itX = xNodes.begin(), itY = yNodes.begin(), itZ = zNodes.begin(), xEnd = xNodes.end(), yEnd = yNodes.end(), zEnd = zNodes.end();  itX != xEnd && itY != yEnd  && itZ != zEnd; ++itX, ++itY, ++itZ)
{
   rotateVertex(rotMatrix, *itX, *itY, *itZ);
}
Изначально был такой вариант
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #11 : Ноябрь 03, 2015, 11:36 »

Игорь, а у меня формат стороннего файла на входе именно по координатам. Я решил не заниматься перетасовками из векторов в структуру и обратно
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #12 : Ноябрь 03, 2015, 11:47 »

Цитировать
m_ax, а это хорошо, что у нас end() вызывается на каждой итерации?
Я очень сомневаюсь, что это может привести хоть сколь-нибудь заметному эффекту, даже без оптимизации)

Кстатии, если посмотреть на стандартные алгоритмы такие как, например, copy, transform и т.д. которым на вход передаётся две  последовательности, то у всех у них размер определяется первой, т.е.:
Код
C++ (Qt)
std::copy(v.begin(), v.end(), res.begin()); // res.end() не передаём
 
 
И я думаю это правильно. Но это так.. мысли вслух)  
Записан

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

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Ноябрь 03, 2015, 11:56 »

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

Сообщений: 2130



Просмотр профиля
« Ответ #14 : Ноябрь 03, 2015, 12:25 »

Кстатии, если посмотреть на стандартные алгоритмы такие как, например, copy, transform и т.д. которым на вход передаётся две  последовательности, то у всех у них размер определяется первой
m_ax, в этом что-то есть.... Но в этом варианте явно видно, кто управляет концом цикла. В моём же случае без дополнительного кода не ясно, кто должен завершать цикл.

Игорь, я умею писать классы с методами и написание класса "координата" меня бы ничему новому не научило бы. Не вижу смысла создавать какие-то структуры, которые будут вносить дополнительные расходы в плане кода. Думаю, что если и появится необходимость в таком классе, то внесение изменений не будет нести катастрофичный характер.
QVector3D для большей гибкости вы можете заменить на QGenericMatrix либо найти другой уже написанный вариант этого класса. Не думаю, что такая задача осталась без внимания.
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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