Попытка заставить итератор Vector перебирать в другом порядке - PullRequest
0 голосов
/ 12 января 2012

У меня двоякий вопрос:

  1. У меня есть вектор объектов и вектор целых чисел, я хочу перебрать вектор моего объекта в порядке целочисленного вектора:

    означает, что если {water,juice,milk,vodka} - это мой объектный вектор, а {1,0,3,2} - это мой целочисленный вектор, я хочу иметь константный итератор для моего объекта-вектора, который будет содержать сок для первого объекта, воду для второго, водку и последнее молоко.

    Есть ли простой способ сделать это?

  2. предположим, у меня есть функция, возвращающая константный итератор (itr) в неизвестный (но доступный) векторный смысл, яможно использовать (itr.getvalue()), но у меня нет размера вектора, по которому я итерирую, есть ли способ сделать цикл while и узнать конец или вектор средствами итератора?

Ответы [ 4 ]

2 голосов
/ 12 января 2012

Вопрос 1:

Опуская большую часть стандартного шаблона, необходимого для правильного итератора, вот как это будет работать:

template<typename Container, typename Iterator>
class index_iterator
{
public:
  typedef typename Container::value_type value_type;
  index_iterator(Container& c, Iterator iter):
    container(c),
    iterator(iter)
  {
  }
  value_type& operator*() { return container[*iterator]; }
  index_iterator& operator++() { ++iterator; return *this; }
  bool operator==(index_iterator const& other)
  {
    return &container == &other.container && iterator == other.iterator;
  }
  // ...
private:
  Container& container;
  Iterator iterator;
};

template<typename C, typename I>
 index_iterator<C, I> indexer(C& container, I iter)
{
  return index_iterator<C, I>(container, iter);
}

Тогда вы могли бы написать, например,

std::vector<std::string> vs;
std::vector<int> vi
// fill vs and vi
std::copy(indexer(vs, vi.begin()),
          indexer(vs, vi.end()),
          std::ostream_iterator<std::string>(std::cout, " "));

Вопрос 2:

Нет, это невозможно.

0 голосов
/ 12 января 2012

Другие уже рассмотрели номер 1. Что касается номера 2, это сводится к вопросу о том, что вы готовы назвать итератором. Конечно, можно определить класс, который будет примерно выполнять то, о чем вы просите - один объект, который представляет текущую позицию и имеет некоторый способ выяснить, когда он будет увеличен в максимально возможной степени.

Большинство людей называют это чем-то вроде range, а не итератором. Вы должны использовать его несколько иначе, чем обычный итератор. Большинство итераторов используются путем явного сравнения их с другим итератором, представляющим конец диапазона. В этом случае вы должны передать две отдельные позиции при создании «итератора» (одну для начальной / текущей позиции, другую для конечной позиции) и перегрузить operator bool (для наиболее очевидного выбора), чтобы укажите, была ли текущая позиция увеличена после конца. Вы бы использовали что-то вроде: while (*my_iterator++) operator_on(*my_iterator); - совсем немного отличается от использования обычного итератора.

0 голосов
/ 12 января 2012

Я хочу иметь константный итератор для моего объекта-вектора, который будет содержать сок для первого объекта

typedef std::vector<Drink> Drinks;
Drinks drinks;
drinks.push_back("water");
drinks.push_back("juice");
drinks.push_back("milk");
drinks.push_back("vodka");
Drinks::const_iterator i = drinks.begin();

константный итератор (itr) для неизвестного (нодоступно) вектор

Drinks::const_iterator itr = some_func();
while (itr != drinks.end()) {
   doStuff;
   ++itr;
}
0 голосов
/ 12 января 2012

1

#include <iostream>
#include <vector>

std::vector<std::string>  foods{"water", "juice", "milk", "vodka"};
std::vector<unsigned int> indexes{1,0,3,2};

for (int i : indexes) { // ranged-for; use normal iteration if you must
   std::cout << foods[i] << " ";
}

// Output: juice water vodka milk 

Демонстрационная версия

Если вы действительно хотите обернуть это поведение в один итератор для foods, это можно сделать, но этостановится немного сложнее.


2

предположим, у меня есть функция, возвращающая константный итератор (itr) в неизвестный (но доступный) векторный смысл, я могу использовать (itr.getvalue ()) но у меня нет размера вектора, по которому я итерирую, есть ли способ сделать цикл while и узнать конец или вектор с помощью итератора?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...