Is a lambda-expression that only captures by reference guaranteed not to throw?

178 views Asked by At

With C++20 P0052's scope_guards (and many other flavors of scope guards), consider this typical use case:

auto f = std::fopen(/*...*/);
scope_exit guard_f([&](){ std::fclose(f); });

The code relies on that the lambda expression itself (the construction of the closure object) doesn't throw. How does the C++ standard guarantee that?

I read the chapter(ยง7.5.5 Lambda expressions) of the standard, and found no saying about the noexceptness of lambda constructors.

1

There are 1 answers

0
Brian Bi On

In interpreting the standard, we should assume that the evaluation of an expression doesn't have any observable effects other than what the standard either explicitly specifies (other than in cases where the standard specifies that the behaviour is undefined, unspecified, or implementation-defined).

Surely you would agree that the evaluation of the expression 1 + 1 can never throw. Must there be a sentence in [expr.add] (which governs the built-in addition operator) explicitly stating that an exception is not thrown? Equally, there does not need to be any such sentence in [expr.prim.lambda]. (Though of course the creation of a lambda closure object can throw, if the initialization of any capture throws. This is implied by [expr.prim.lambda.capture]/15, which states that the entities that are captured by copy are direct-initialized, and is explicitly accounted for, e.g. by [except.spec]/6 and [intro.execution]/3.3. All references are to C++20.)