Как `std::mem_fn` обнаруживает отсутствие исключений в gcc 7.1.0

С gcc 7.1.0 std::mem_fn может обнаружить noexcept-ness по указателю на функцию-член. Как оно работает? Я думал noexcept спецификатор не был частью типа функции?


Что еще более запутанно, так это когда я удаляю спецификатор noexcept для одного метода из https://wandbox.org/permlink/JUI3rsLjKRoPArAl все значения noexcept меняются, как показано здесь https://wandbox.org/permlink/yBJ0R4PxzAXg09ef. И когда кто-то не исключает, все не исключают. Как? Это ошибка?

1 ответ

Решение

Поведение, которое вы видите с GCC в режиме C++14, является ошибкой, см. https://gcc.gnu.org/PR77369

В комментариях вы спрашиваете:

Кроме того, объявление mem_fn, поскольку C++17 не имеет перегрузки noexcept, тогда как он обнаруживает эту информацию от пользователя?

Это не должно иметь перегрузку noexcept, рассмотрите этот код C++17:

template<typename T>
  constexpr bool is_noexcept_callable(T t) {
    return noexcept(t());
  }

void f() noexcept { }
void g() { }
static_assert( is_noexcept_callable(f) );
static_assert( !is_noexcept_callable(g) );

Там нет необходимости иметь исключение перегрузки is_noexcept_callable потому что в C++17 спецификация исключений является частью типа, поэтому вся информация уже закодирована в типе T, Когда вы создаете экземпляр std::mem_fn с указателем на noexcept(true) Функция знает, что вызов этой функции не может сгенерировать. Когда вы создаете его с noexcept(false) Функция знает, что может бросить.

Наконец, причина, по которой ваш пример не компилируется в режиме C++17 с GCC 7.1, заключается в https://gcc.gnu.org/PR80478 который исправлен в GCC 7.2 (поэтому обновите свой компилятор).

Другие вопросы по тегам