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

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

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

15

Решение

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

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

10

Другие решения

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

#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 может быть распечатан.

6

По вопросам рекламы [email protected]