Рассмотрим следующие фрагменты кода:
Версия (1)
void q() {}
class B {
void f() noexcept(noexcept(q())) {q(); }
decltype(&B::f) f2;
};
Версия (2)
void q() {}
class B {
void f() noexcept(true) {q(); }
decltype(&B::f) f2;
};
Версия (3)
void q() {}
class B {
void f() noexcept {q(); }
decltype(&B::f) f2;
};
Все версии GCC компилируют эти фрагменты кода без каких-либо ошибок или предупреждений (включая версию с транком).Все версии Clang, которые поддерживают C ++ 17, запрещают версию (1) и (2), но не версию (3), со следующей ошибкой:
<source>:4:16: error: exception specification is not available until end of class definition
decltype(&B::f) f2;
^
Примите во внимание, что стандарт определяет noexcept
как эквивалент noexcept(true)
[кроме.spec].Таким образом, версия (2) и версия (3) должны быть эквивалентны, что они не для лязг.
Таким образом, следующие вопросы: В какой момент спецификации исключений должны быть оценены в соответствии с C ++ 17стандарты?И, если некоторые приведенные выше коды являются недействительными, что является рациональным?
Абстрактный фон для тех, кто интересуется:
template <typename F>
struct result_type;
template<typename R, typename C, typename... Args>
struct result_type<R(C::*)(Args...)> {
using type = R;
}; // there may be other specializations ...
class B {
int f() noexcept(false) { return 3; }
typename result_type<decltype(&B::f)>::type a;
};
Этот код должен быть действительным, по крайней мере, доC ++ 14, потому что noexcept
не был частью типа функции (для clang он скомпилирован до версии 3.9.1).Для C ++ 17 нет способа сделать это.