Подтвердить что ты не робот

Неявные сгенерированные члены и noexcept

Недавно я начал добавлять новую спецификацию noexcept для перемещения конструкторов/назначений, где это возможно. Теперь я начал задаваться вопросом, как выглядит спецификация исключения неявных сгенерированных функций-членов. Поскольку функция noexcept move позволяет использовать более эффективные пути кода (например, при изменении размера a vector), я надеюсь, что они будут объявлены как неэксключные, когда это возможно. У меня возникли проблемы с пониманием того, что стандарт должен сказать об этом, и поэтому попробовал следующий код в 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? Кроме того, является obseved поведение для foobar правильного или просто ошибки компилятора в gcc4.6?

4b9b3361

Ответ 1

Ошибка библиотеки - она ​​показывает 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 не было noexcept-correct, и это было рассмотрено в gcc 4.7,


В том случае, когда функции с неограниченным числом членов не исключают, это описано в п. 15.4/14. В принципе, это noexcept, если все функции, которые ему нужно вызвать, это все noexcept.

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