2013-12-22 4 views
3

В настоящее время я пишу исключающий код код, и мой дизайн не требует никакой гарантии броска для set :: find method. Я предполагаю, что объект компаратора всегда преуспевает. Это означает, что метод set :: find всегда будет успешным?std :: set :: найти исключения гарантии

Я подумал о такой возможности после того, как увидел, что согласно http://en.cppreference.com/w/cpp/container/set/erase, метод set :: erase, с тем же предположением, всегда должен быть успешным и, возможно, в нем есть находка (тогда это было бы безусловно достойно комментария в документация!)

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

+0

Я не уверен в стандарте или каких-либо гарантиях для установленных или каких-либо stl-контейнеров, но я скажу это. Один раз я вызываю vector :: erase (v.end()) .. Он выбросил исключение .. Я часами пытался выяснить, почему. Оказывается, мой вектор пуст. Не уверен, что это все еще происходит, или если std :: set имеет эту проблему, но это случилось со мной в gcc 4.8.1 для Windows. Мне пришлось выполнить оператор if, проверяющий, будет ли 'vector :: find! = V.end() '. Я думаю, вам, возможно, придется это сделать. Это может быть единственный раз, когда вы не получите исключение точно? – Brandon

+0

@CantChoose Это неопределенное поведение для пустого вектора, как и для непустого вектора. Вы не можете стереть первый элемент в прошлом ... – IInspectable

+0

@CantChooseUsernames Вы должны быть рады, что выбрали исключение. Это неопределенное поведение AFAIK и, возможно, стерло ваш жесткий диск;) – dyp

ответ

1

std::set::find:

Возвращаемое значение

итератор элемента с ключом key. Если такой элемент не найден, возвращается итератор past-the-end (см. end()).

Ни в документации, ни в Стандарте C++ явно не указаны гарантии безопасности исключений. Тем не менее, те же самые правила, провозглашенные для std::set::erase применять здесь (§23.2.4.1 гарантии безопасности Исключения [associative.reqmts.except]):

erase(k) не бросает исключение, если это исключение не выбрасываются Compare объекта контейнера (если есть).

В сущности, если Compare объект не генерирует исключение, std::set::find не бросает. Бьерн Страуструп имеет следующие сказать в The C++ Programming Language, Special Edition - Appendix E:

К счастью, предикаты все, что может вызвать исключение редко. Однако при рассмотрении безопасности исключений должны учитываться заданные пользователем <, == и != предикаты.

Если вы не указали какие-либо определенные пользователем предикаты, вы можете предположить, что std::set::find не генерирует исключение. Если да, вы должны отметить их как noexcept, чтобы безопасно работать в вашем сценарии.

0

C++ 11 §23.2.4.1 гарантия безопасности Исключения [associative.reqmts.except] перечислены все требования безопасности, за исключение для ассоциативных контейнеров (включая set) и нет никакого упоминания сделано из find. Так что нет, стандарт не гарантирует, что find никогда не выбрасывает.

В отсутствие неопределенного поведения и предположения о нераспространяющемся компараторе я считаю крайне маловероятным, что существует реализация стандартной библиотеки C++, которая будет генерировать исключение из set::find.Я бы лично быть комфортно (а) оберточным set::find в функции в noexcept переадресации, так что программа будет вылетать, если такие «невозможной», что никогда не происходит, или (б) упаковки конкретного set::find вызова в

auto it = foo.end(); 
try { 
    it = foo.find(bar); 
} catch(...) {} 

и просто рассматривая исключение как «не найденное».

Обратите внимание, что отношение упорядочения ассоциативных контейнеров является легко упускаемым источником неопределенного поведения: § 23.2.4/2 требует, чтобы отношение упорядочения приводило к строгим слабым упорядочениям (как описано в п. 25.4) по ключевым элементам. Ассоциативный контейнер, созданный с отношением упорядочения, который равен , не, строгий слабый порядок не имеет определенного поведения, одним из возможных результатов которого является исключение из find.

+0

Я легко мог представить, что исключение выбрасывается, если компаратор неправильно возвращает строгий слабый порядок объектов. Могу поверить, что Dev Studio может. – StilesCrisis

+0

@StilesCrisis Да, исключение - это возможный результат неопределенного поведения в программе, как и любой другой воображаемый результат. – Casey

+0

Написание моего оператора <, чтобы всегда возвращать false, нелогично, но на его лице он не собирается бросать. Стоя в одиночку, это не неопределенное поведение - это просто неправильные результаты. – StilesCrisis

Смежные вопросы