В стандартной библиотеке MSVC 2017 поставляется примерно такая реализация std::size:
template<class T, size_t S>
constexpr size_t size(T(&)[S]) noexcept
{
return S;
}
Действительно, стандарт не запрещает функциям constexpr бросать исключения, но здесь и функция тривиальная. Компилятор может и сам вычислить noexcept, в других случаях MSVC 2017 прекрасно это делает, например:
template<typename T>
constexpr auto Plus(T left, T right)
{
return left + right;
}
static_assert(noexcept(Plus(1,3)), "fail"); // OK в MSVC 2017
Тогда зачем noexcept: просто так захотелось, так надо, или это ошибка?
Начиная с С++17 noexcept входит в тип функции, но при этом как и возвращаемый тип, не является частью сигнатуры. Поэтому и требуется явное указание, если нужно чтобы функция действительно считалась noexcept.
Например, данный код валиден только начиная с c++17:
void f() noexcept {}
int main()
{
using P = void (*)() noexcept; // c++14 не позволяет тут `noexcept`
P fp = &f;
}
Это позволяет в частности делать такое разделение:
void g() {}
P fp = &f;
P gp = &g; // ошибка из-за отсутствия `noexcept` у `g`
Наличие constexpr у функции не даёт каких-либо преференций считать её noexcept. Хотя до c++17 нечто подобное предполагалось при использовании оператора noexcept.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости