Различное использование noexcept - PullRequest
4 голосов
/ 28 февраля 2020

В книге Язык программирования C ++ написано, что вы можете объявить функцию условно noexcept. Например:

template<typename T>
void my_fct(T& x) noexcept(std::is_pod<T>::value);

noexcept принимает предикат, который должен быть постоянным выражением (в примере std::is_pod<T>::value).

Однако в книге также написано:

Оператор noexcept() принимает выражение в качестве аргумента и возвращает true, если компилятор знает, что он не может выдать, и false в противном случае.

Принимая это в учтите, что

constexpr bool f() { return true; }

void g() noexcept(f())
{
    f();
}

g() помечен как noexcept или нет? Я вижу две возможности:

  1. Вызов f() оценивается во время компиляции, потому что он помечен constexpr, он возвращает true и в результате g() помечается noexcept .
  2. Компилятор не может определить, что f() не может выдать исключение, поскольку f() не помечено noexcept. В результате g() не помечается noexcept.

Что происходит? Как выбрать то или иное поведение для noexcept?

Ответы [ 2 ]

5 голосов
/ 28 февраля 2020

Грамматика языка позволяет только указателю noexcept появляться в этой позиции.

Следовательно, ваша первая точка верна. g() будет помечено noexcept, поскольку f() возвращает true.

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

void g() noexcept(noexcept(f()))
{
    f();
}

, что будет ведите себя согласно второму пункту.

3 голосов
/ 28 февраля 2020

Что происходит?

1.

Как выбрать то или иное поведение для noexcept?

Использование контекста. Объявление функции - единственный контекст, в котором используется значение предиката.

Если вы хотите использовать оператор noexcept в предикате noexcept, вам нужно написать:

void g() noexcept(noexcept(f())) 
...