Вы можете определить свой собственный прокси-класс итератора, который оборачивает итератор карты и передает ему все операции. Тогда ваш класс может иметь специальное «конечное» значение, и вы можете вернуть это значение для not found. Для сравнения, вызывающей стороне нужен способ получить конечный прокси-итератор.
Если вы хотите быть действительно флэш-памятью, ваш итератор может знать, как «шагнуть вперед» от конца одной содержащейся карты до начала следующей, чтобы его можно было использовать для перебора всех карт в коллекция. По общему признанию не в ключевом заказе.
Другой вариант - вернуть пару (итератор, bool). Ваш «глубокий поиск» уже не возвращает тип, который функции поиска обычно возвращают при вызове с контейнером (то есть тип итератора контейнера), так что вы можете просто пойти на полное изменение.
Итераторы не обязаны конструироваться по умолчанию, хотя часто это так. Так что на самом деле немного сложно иметь «бессмысленный итератор» и быть правильно переносимым. Однако вы можете попробовать создать итератор карты по умолчанию, и, если он работает в вашей реализации, используйте его в случае, если bool имеет значение false.
Я не уверен, что Boost.Optional делает с типами, которые не могут быть созданы по умолчанию, но это может быть полезно в качестве возвращаемого значения.