Оператор присваивания перемещения часто должен объявляться как noexcept (то есть для хранения типа в контейнерах STL). Но идиома копирования и замены позволяет определять операторы копирования и перемещения в одном фрагменте кода. Что делать со спецификатором noexcept в этом случае? Конструкция копии может генерироваться, но я сомневаюсь, что она может нарушать спецификатор noexcept.
// Is it correct considering that T copy constructor can throw?
T& operator=(T other) noexcept;
Поскольку копия сделана на вызывающий абонент боковая сторона вызова, это не часть того, что делает ваша функция. Поэтому он не может контролироваться вашей функцией, и, следовательно, вы не можете включить эту информацию в 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
обещание было выполнено. В противном случае, терминатор будет вызван раньше catch
может быть распечатан.