Поиск владельца итератора STL - PullRequest
6 голосов
/ 17 декабря 2008

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

Если (как я подозреваю) ответ - нет, то почему бы и нет?

edit: спасибо за ряд быстрых и (в основном) точных ответов. Эван Теран прибивает его. Я вообще не думал об оптимизации, но теперь это очевидно.

Несколько человек спросили, для чего я хочу это сделать. В этом нет ничего страшного. У меня есть объект, который инициализируется с вектором и итератором, указывающим на вектор. Было бы мило и удобно, если бы я мог инициализировать объект просто с помощью итератора, потому что тогда я мог бы конвертировать vector::iterator s непосредственно в этот объект (это звучит странно, но имеет смысл в конкретном случае). Но это совсем не важно.

Ответы [ 7 ]

7 голосов
/ 17 декабря 2008

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

5 голосов
/ 17 декабря 2008

Нет способа заставить эту работу. Причина проста: добавление пути к итераторам для получения контейнера, на который они указывают,

  • Бессмысленно. Итераторы перебирают коллекцию. Как сказал другой, только это, не более того.
  • Не совместимо с требованиями итератора. Помните, что указатель является итератором произвольного доступа. Помещение указателя контейнера в итератор было бы бесполезным для алгоритмов, поскольку они намеревались быть общими, отделенными от конкретных реализаций итератора. Указатель, используемый в качестве итератора, не может иметь указатель обратно на массив, из которого он был взят в качестве члена.

Вы говорите, что это нужно для проверки диапазона. Вы можете предоставить конечный итератор, который указывает одну после последней действительной позиции итератора диапазона. Проверьте, не находится ли ваша текущая позиция в конце. Это все, что вам нужно сделать для проверки диапазона.

3 голосов
/ 17 декабря 2008

Вы не можете получить контейнер из итератора обычным способом. В качестве примера того, почему простой итератор может использоваться как итератор:

#include <algorithm>
#include <cstdio>
#include <cstring>

int
main(int argc, char *argv[])
{
        const char s[] = "Hello, world!";
        const char *begin = s;
        const char *end = s + strlen(s);

        std::for_each(begin, end, putchar);

        return 0;
}

Как вы можете извлечь исходную строку из указателя (если она не указана в начале строки)?

Однако, если вам нужна эта функциональность, вы всегда можете реализовать свою собственную оболочку вокруг итератора, которая хранит ссылку на контейнер.

2 голосов
/ 17 декабря 2008

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

Вы ДОЛЖНЫ знать все векторы-кандидаты, по которым нужно проверять заранее, и это не общий способ получить контейнер, к которому принадлежит итератор.

Однако вы можете определить расширение итераторов произвольного доступа, украсив итератор произвольного доступа чем-то, содержащим указатель на вектор создания. Скорее всего, это будет немного не элегантно, неэффективно и неудобно. Посмотрите, можете ли вы сначала переписать код, чтобы избежать этой необходимости.

1 голос
/ 17 декабря 2008

STL не допускает этого.

Итераторы Vecor, например, могут быть реализованы просто как указатель. И нет общего способа извлечь объект из указателя, указывающего на некоторые данные, которые объект выделил.

0 голосов
/ 17 декабря 2008

Как предлагалось ранее, лучше переписать ваш код, чтобы вам не понадобилось такое поведение. Это то же самое, что держать монету, но вы не знаете, откуда она взялась, если не заметили это на бумаге.

Если вы не можете переписать код, вы все равно можете ввести объект-оболочку, который содержит указатель на контейнер и сам итератор. Зачем тебе это конкретно?

0 голосов
/ 17 декабря 2008

Я не верю, что есть открытый метод для этого. Причина в том, что это не цель итератора. Конечно, нет технической причины, по которой итератор не может содержать указатель на свой родительский контейнер. Даже если он реализован таким образом, что этот указатель не требует, он все равно может его удерживать.

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

Могу ли я спросить, каков ваш вариант использования, что вам нужно знать «диапазон» контейнера с итератором?

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