Неявные сгенерированные члены и noexcept - PullRequest
18 голосов
/ 07 февраля 2012

Недавно я начал добавлять новую спецификацию noexcept для перемещения конструкторов / назначений, где это возможно.Теперь я начал задаваться вопросом, как выглядит спецификация исключений неявных сгенерированных функций-членов.Поскольку наличие noexcept функций перемещения позволяет использовать более эффективные пути кода (например, при изменении размера vector), я надеюсь, что они объявляются как noexcept, когда это возможно.У меня были проблемы с пониманием того, что стандарт говорит об этом, и поэтому попробовал следующий код в g ++ 4.6 (с -std=c++0x), чтобы получить некоторое представление об этом:

struct foobar{};
int main()
{
    foobar a, b;
    std::cout<<std::boolalpha
             <<noexcept(foobar())<<", "<<noexcept(foobar(a))<<", "
             <<noexcept(a = b)   <<", "<<noexcept(a = std::move(b))<<", "
             <<noexcept(foobar(std::move(a)))<<std::endl;
}

Это дало мне выводTrue, True, True, False, False, что означает, что по умолчанию и скопировать конструктор / присваивание, где noexcept, в то время как операция перемещения, где нет.

Теперь на мой вопрос:

При каких обстоятельствах неявно генерируемые (или дефолтные) функции-члены объявляются как noexcept?Кроме того, правильное поведение для foobar корректно или просто ошибка компилятора в gcc4.6?

1 Ответ

18 голосов
/ 07 февраля 2012

Ошибка библиотеки - она ​​показывает true, true, true, true, true в gcc 4.7.

И ошибка не в том, что сгенерированные конструкторы перемещения не исключение, но std::move не помечено как noexcept, как мы видим из дополнительных тестов:

std::cout << noexcept(a = static_cast<foobar&&>(b)) << ", "  // true
          << noexcept(foobar(static_cast<foobar&&>(b))) << ", " // true
          << noexcept(std::move(b)) << std::endl;   // false

Большинство библиотечных функций в gcc 4.6 были не правильными, и это было исправлено в gcc 4.7 ,


Что касается случаев, когда неявно сгенерированные функции-члены не являются исключениями, это задокументировано в §15.4 / 14. По сути, это noexcept, если все функции, которые нужно будет вызвать, являются noexcept.

Неявно объявленная специальная функция-член (раздел 12) должна иметь спецификацию исключений . Если f неявно объявленный конструктор по умолчанию, конструктор копирования, конструктор перемещения, деструктор, назначение копирования оператор или оператор присваивания перемещения, его неявное исключение-спецификация определяет type-id T тогда и только тогда если T разрешено спецификацией исключений функции, непосредственно вызванной неявным определением f; f должен разрешить все исключения, если любая функция, которую она непосредственно вызывает, разрешает все исключения, и f не должны разрешать никаких исключений если каждая функция, которую она непосредственно вызывает, не допускает никаких исключений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...