Поиск владельца итератора STL

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

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
1 615
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

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

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

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

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

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

#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;
}

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

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

Он демонстрирует, почему вы не можете получить контейнер из итерации, на конкретном и простом примере ...

Judge Maygarden 18.12.2008 00:12

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

Lightness Races in Orbit 23.10.2018 17:22

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

Вам НЕОБХОДИМО знать все векторы-кандидаты, чтобы проверить их заранее, и это не общий способ получить контейнер, которому принадлежит итератор.

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

Это первое предложение определенно опирается на неустановленные детали реализации, и его будет очень сложно поддерживать. Я бы предпочел реализовать декоратор; по крайней мере, тогда он гарантированно будет работать всегда и сделает мои намерения очевидными.

jdmichal 17.12.2008 22:04

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

Thomas Kammeyer 17.12.2008 22:54

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

Thomas Kammeyer 29.11.2016 20:27

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

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

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

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

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

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

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

Другие вопросы по теме