Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does anything prevent std::optional::value_or() from being conditionally noexcept?

Here's the definition of value_or() from the C++17 standard:

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> is false, the program is ill-formed.

(the rvalue overload is similar)

The effect of value_or is described as equivalent to return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));

operator bool is noexcept. operator* is not noexcept (even though it doesn't throw, probably because it can still fail with UB if used when the optional does not contain a value). However, we are guaranteed to never try to return the contained value unless we have one.

So couldn't value_or be declared noexcept given is_nothrow_copy_constructible<T> && noexcept(static_cast<T>(std::forward<U>(v)))?

like image 524
knatten Avatar asked May 03 '18 18:05

knatten


1 Answers

noexcept is used extremely sparingly in the c++ standard. That is about the only barrier.


While this answers the question, the next question is "why is it used sparingly". This is an extra bit of information you might find useful; if this was the core of the answer, I'd include more quotes instead of links. The paper numbers should outlive the specific hyperlinks I'm using, so there is that.

N3279 is the conclusion of a discussion about noexcept. Basically, anything with a narrow contract (that can exhibit UB) and isn't a move ctor or dtor is never marked noexcept.

Here are the guidelines:

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.

I wasn't party to the discussion, but basically the idea is that the compiler can add exceptions to those methods.

I believe this is called the Lakos rule. To change it, take it up with the committee.

N3248 is the paper that brought up issues with noexcept. Mostly it is about testing.

like image 181
Yakk - Adam Nevraumont Avatar answered Sep 30 '22 06:09

Yakk - Adam Nevraumont