Очевидный, но неверный подход
Вы не можете просто выполнить итерацию по списку, сравнивая каждое значение итератора с вашим «кандидатом».
Стандарт C ++ 03 неясен в отношениидопустимость ==
применяется к итераторам из разных контейнеров (комментарий Манкарса по ссылкам ответа Наваза http://www.open -std.org / jtc1 / sc22 / wg21 / docs / paper / 2009 / n2948.html # 446 )некоторые компиляторы (например, режим отладки VC ++ 2005) предупреждают, если вы это делаете, но, несмотря на все это, он может действительно работать надежно в зависимости от вашего компилятора / библиотек - проверьте его документацию, если вам не нужна переносимость.
Стандарт C ++ 11 очень явный, вы не можете сравнивать итераторы с разными контейнерами :
§ 24.2.5 Область == для прямых итераторовэто итераторы по одной и той же базовой последовательности.
Итак, ответы на этот вопрос, основанные на operator==
, сомнительны сейчас и недействительны в будущем.
Частодействительный подход
Что заu может сделать - выполнить итерацию по списку, сравнивая адрес элементов (т.е. &*i
) с адресом объекта, на который указывает ваша другая итерация.
Комментарий Манкарса предупреждает, что это может не работать так, как предназначено для объектов, предоставляющих свои operator&
.Вы можете обойти это, используя std::addressof
или для C ++ 03 версию Boost
В комментарии Мартина упоминается, что вы должны принятьИтератор-кандидат, для которого вы тестируете членство в списке, безопасно разыменован, т. е. не равен итератору end()
для контейнера, из которого он получен.Как отмечает Стив - это довольно разумное предварительное условие и никого не должно удивлять.
(Это хорошо для всех стандартных контейнеров, поскольку хранимые элементы никогда не имеют одинаковый адрес, но в целом пользовательский-определенные контейнеры могут позволить неравным итераторам обращаться к одному и тому же объекту-значению (например, поддерживать циклы или оптимизировать стиль "шаблон веса"), в этом случае этот подход потерпит неудачу. Тем не менее, если вы пишете такой контейнер, вы, вероятно,позиция для проектирования для безопасного сравнения итератора.)
Реализация:
template <class IteratorA, class IteratorB, class IteratorC>
inline bool range_contains(IteratorA from, const IteratorB& end,
const IteratorC& candidate)
{
while (from != end)
if (&*from++ == &*candidate)
return true;
return false;
}
Примечания:
- Это принимает стандартный подход библиотеки для принятия диапазона итераторапозиции для поиска.
- Разрешается варьировать типы каждого итератора, поскольку существуют проблемы с переносимостью, например контейнеры, в которых
begin()
возвращает iterator
, но end()
возвращает const_iterator
. - Итераторы, отличные от
from
, берутся по ссылке const
, поскольку итераторы иногда могут быть нетривиальными объектами (т.е. слишком большимиGe, чтобы вписаться в реестр, относительно дорого, чтобы скопировать).from
необходимо по значению, поскольку оно будет увеличиваться в диапазоне.