Как использовать noexcept в операторе присваивания с идиомой копирования и замены?

оператор присваивания перемещения часто должен объявляться noexcept (т. е. для хранения типа в контейнерах STL). Но идиома копирования и подкачки позволяет определять операторы копирования и перемещения в одном фрагменте кода. Что делать с спецификатором noexcept в этом случае? Конструкция копирования может бросить, но я сомневаюсь, что она может нарушить спецификатор noexcept.

// Is it correct considering that T copy constructor can throw?
T& operator=(T other) noexcept;

2 ответов


С копия на звонящего!--5--> боковая вызова, это не является частью того, что делает ваша функция. Поэтому он не может управляться вашей функцией и, следовательно, вы не можете включить эту информацию в noexcept спецификация.

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


как обычно Даниель Фрей и правильно. Все, что я хочу, это показать фрагмент кода, который иллюстрирует суть.

#include <iostream>

struct foo {

    foo() = default;

    foo(const foo&) {
        std::cout << "throw\n";
        throw 1;
    }

    foo& operator =(foo) noexcept {
        return *this;
    }
};

int main() {

    foo f, g;
    try {
        f = g; // throws
    }
    catch(int) {
        std::cout << "catch\n";
    }
}

при компиляции с gcc 4.8.1 (-std=c++11 -Wall -Wextra -pedantic) это не дает никаких предупреждений. Запуск кода приводит к следующему выводу:

throw
catch

поэтому конструктор копирования бросает при вызове, но это не рассматривается внутри operator =() и, следовательно,noexcept обещание было выполнено. В противном случае, terminate будет вызван до catch может быть распечатана.