Как перегрузить operator-> на «генерирующий» итератор? - PullRequest
3 голосов
/ 27 июля 2010

Я определяю тип итератора, который не хранит свое текущее значение явно. Вместо этого это обертка вокруг другого итератора, которая возвращает std::pair s значений итератора и другого значения. Соответствующая часть определения класса:

class MyIterator : public std::iterator<input_iterator, std::pair<Foo *, Bar *> > {

    FooPtrIterator d_iter;
    Bar d_bar;

    public:

        MyIterator(FooPtrIterator iter, Bar const &bar)
        :
            d_iter(iter),
            d_bar(bar)
        { }

        // Returning by value, not storing the pair itself.
        value_type operator*() const {
            return std::make_pair(*d_iter, &d_bar);
        }

        // Can't return by value!
        ??? operator->() const {
            return ???;
        }

};

Теперь у меня возникают проблемы при перегрузке operator->, потому что я должен вернуть указатель или что-то еще, что само по себе поддерживает operator->.

Я мог бы просто сохранить текущий std::pair как член класса:

    value_type d_current;

Однако, это вызывает у меня проблемы в конструкторе, потому что в этот момент я не могу знать, является ли FooPtrIterator iter допустимым итератором, поэтому я не могу разыменовать его для предоставления d_current значения.

Я также могу заставить operator-> вернуть boost::shared_ptr<value_type>, но это ужасный хак с большими накладными расходами, чем необходимо.

У меня такое ощущение, что этот "генерирующий" итератор не должен существовать. Это так или есть другой способ обойти это?

1 Ответ

2 голосов
/ 27 июля 2010

Я бы предложил создать собственный класс, содержащий пару Foo * и Bar *, например:

class MyPair  {
private:
  FooPtrIterator foo;
  Bar bar;

public:
  MyPair(const FooPtrIterator& it, const Bar& b) : foo(it), bar(b)  {}

  Foo* first() { return *foo; }
  Bar* second() { return &bar; }
};

Тогда просто используйте его внутри своего класса итератора вместо двух значений. Вам придется изменить -> first и -> second на -> first () и -> second () в вашем коде, но это должно быть приемлемым изменением.

...