Должен ли я использовать throw () при реализации не-бросающего свопа? - PullRequest
6 голосов
/ 13 ноября 2010

При реализации идиома не-бросающего свопа я должен использовать throw()?

namespace A
{
   struct B
   {
     void swap( B& other ) throw()
     { /* fancy stuff that doesn't throw */ }
   };

   void swap( B& lhs, B& rhs ) throw()
   { lhs.swap(rhs); }
}

namespace std
{
   template<>
   void swap( A::B& lhs, A::B& rhs ) throw()
   { lhs.swap(rhs); }
}

В частности, я беспокоюсь о том, чтобы поставить спецификацию throw() для специализации std::swap.

Бонусный вопрос:
Отличается ли ответ при использовании ключевого слова C ++ 0x noexcept?

Ответы [ 3 ]

4 голосов
/ 13 ноября 2010

В C ++ 03 вы можете поместить это туда, но если это правда, что модные вещи не выдают, это в основном просто документация.Он может влиять или не влиять на производительность, добавляя эквивалент try / catch(...) { std::unexpected(); } вокруг вызовов функции: зависит от реализации, сможет ли она сделать это, не влияя на производительность.

Если вы планируете использовать noexcept оператор (5.3.7) в C ++ 0x, тогда внезапно становится целесообразным иметь спецификации исключений без выбрасывания, так что оператор дает «правильный» ответ.Я на самом деле не знаю, для чего нужен оператор noexcept, но если есть умное обобщенное использование для него, например, алгоритмы, которые становятся более эффективными, когда что-то не выбрасывает, то я думаю, что это станет необходимым для маркировки функцийкак исключение броска, чтобы получить любую выгоду.

Например:

void foo() noexcept;
void bar();

template <void(*FUNC)()>
void generic_thing() {
    if (noexcept(FUNC()) {
        // this won't throw, perhaps we can somehow take advantage of that
        FUNC();
    } else {
        // this might throw
        FUNC();
    }
}

Спецификации исключений старого стиля ( динамические-исключения-спецификации ) устарели вC ++ 0x (и бессмысленно в C ++ 03).

3 голосов
/ 13 ноября 2010

Это не очень хорошая идея, нет.Причина в том, что стандарт знает, что порой невозможно обеспечить корректность throw(), для чего и был изначально введен throw().В частности, в случае шаблонов, где исключение может быть или не быть вызвано в зависимости от реализации, невозможно проверить правильность без создания экземпляра шаблона.Поэтому стандарт даже не требует от компиляторов применять спецификатор исключений;на самом деле, запрещает реализации отклонять выражение «просто потому, что при выполнении оно выдает или может выдать исключение, которое запрещающая функция не разрешает» (15.4 / 11).

Еслиthrow() не имеет никакого эффекта, кроме документации, тогда его следует закомментировать;таким образом, по крайней мере, это не представляет опасности для введения в заблуждение наблюдателя-человека.

Случай с noexcept совершенно другой.noexcept приходит по другой причине;это производительности.Если вы можете гарантировать, что компилятор не сгенерирует никаких исключений, то компилятор позволит себе выполнить некоторые оптимизации.Но вам придется делать проверки самостоятельно.Так что, если действительно swap() не бросает (и не должен; это его смысл), тогда указание noexcept - хорошая идея.

1 голос
/ 13 ноября 2010

Реально нет. Спецификации исключений были прекрасной идеей, но реальность их заключалась в том, что они мешали больше, чем помогали большей части кода. Никто не использует их, и они устарели в C ++ 0x. Не тратьте время на написание спецификаций исключений в современном C ++.

...