Вот определение value_or() из стандарта C++ 17:
template <class U> constexpr T value_or(U&& v) const&;Effects: Equivalent to:
return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));Remarks: If
is_copy_constructible_v<T> && is_convertible_v<U&&, T>isfalse, the program is ill-formed.
(перегрузка rvalue аналогична)
Эффект value_or описан как эквивалент return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));.
operator bool - это noexcept. operator* - это нетnoexcept (даже если он не бросает, вероятно, потому, что он все еще может выйти из строя с UB, если используется, когда необязательный параметр не содержит значения). Однако мы гарантированно никогда не попытаемся вернуть содержащееся значение, если оно у нас нет.
Так нельзя ли объявить value_ornoexcept при is_nothrow_copy_constructible<T> && noexcept(static_cast<T>(std::forward<U>(v)))?
@Yakk Я бы подумал, что это отвечает на поставленный вопрос, но сразу же возникает другой: почему он не используется широко?





нет кроме используется в стандарте C++ крайне редко. Это почти единственный барьер.
Хотя это дает ответ на вопрос, следующий вопрос - «почему его используют экономно». Это дополнительная информация, которая может оказаться вам полезной; если бы это было сутью ответа, я бы добавил больше цитат вместо ссылок. Номера на бумаге должны пережить определенные гиперссылки, которые я использую, так что это так.
N3279 - это завершение обсуждения noexcept. По сути, все, что связано с узким контрактом (которое может отображать UB) и не является движением ctor или dtor, никогда не помечается как noexcept.
Вот рекомендации:
Adopted Guidelines
- No library destructor should throw. They shall use the implicitly supplied (non-throwing) exception specification.
- Each library function having a wide contract, that the LWG agree cannot throw, should be marked as unconditionally noexcept.
- If a library swap function, move-constructor, or move-assignment operator is conditionally-wide (i.e. can be proven to not throw by applying the noexcept operator) then it should be marked as conditionally noexcept. No other function should use a conditional noexcept specification.
- Library functions designed for compatibility with “C” code (such as the atomics facility), may be marked as unconditionally noexcept.
Я не участвовал в обсуждении, но в основном идея состоит в том, что компилятор может использовать добавить исключения для этих методов.
Я считаю, что это называется правилом Лакоша. Чтобы изменить это, обсудите это с комитетом.
N3248 - это статья, в которой проблемы без исключения поднимались. В основном это касается тестирования.
Соответствующее руководство по этому вопросу находится на странице 2: только swap() и назначения конструкторов перемещения в библиотеке условно noexcept.
На предыдущем заседании комитета, я думаю, они согласились сделать «типы обертки» условно noexcept на основе операций типов, которые они оборачивают. std::optional и std::variant будут такими типами оболочки.
Это хороший ответ на любой вопрос "Почему X не noexcept".
@morwenn у вас есть документация или ссылки на этот счет, чтобы я мог вставить цитату с указанием авторства?
@Morwenn, что вы имеете в виду, делая тип условным noexcept? Вы имеете в виду какие-то конкретные операции с ними в частности? В C++ 17 optional(optional&& rhs) уже является noexcept, если is_nothrow_move_constructible_v<T> (и аналогично для назначения перемещения). variant делает то же самое, но он должен действовать для всех типов в оболочке.
@Yakk Документ, о котором я упоминал, был [P0884 - Расширение политики noexcept] (wg21.link/P0884], что на самом деле довольно кратко. В документе цитируются std::atomic и предлагаемый std::function_ref в качестве примеров типов упаковки. Я только что проверил протокол собрания (не для всех) и был поднят вопрос о std::optional и std::variant, но фактический ответ состоял в том, что цель статьи заключалась в том, чтобы расширить условную политику noexcept, чтобы не принимать твердых решений, поэтому нет однозначного ответа для этих типов. Очевидно, комитет был решительно за принятие этой статьи.
@knatten Просто еще раз перепроверил документ, и на самом деле он предлагает только условный noexcept для конструктора по умолчанию, конструктора копирования и оператора присваивания копии для типов оболочки, поэтому в отличие от того, что я думал, это никак не повлияет на value_or, извините: /
Условное noexcept не очень часто используется в стандарте C++, может «считаться» чем-то, что препятствует его использованию здесь.