In §[except.throw]
, the standard says that throwing an exception copy-initializes the exception object from the throw expression
Throwing an exception copy-initializes (11.6, 15.8) a temporary object, called the exception object
Why then does the following code compile on C++17?
class Exception {
public:
Exception() = default;
Exception(Exception&&) = delete;
Exception(const Exception&) = delete;
};
int main() {
throw Exception{};
return 0;
}
(https://wandbox.org/permlink/R3WfzfnBAORTLVSy)
Copy initialization does not include any case (from what it seems like to me) that is eligible for prvalue elision. Why then does the above code compile in C++17?
From a recent draft standard
The initialization that occurs in the form of a brace-or-equal-initializer or condition (9.4), as well as in argument passing, function return, throwing an exception (18.1), handling an exception (18.3), and aggregate member initialization (11.6.1), is called copy-initialization.
So T x = T();
is an example of copy-initialization. So is throwing an exception and many other cases.
What copy-initialization does is defined in other parts of 11.6 (along with other forms of initialization). The relevant section on prvalues in initializers is:
If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object
this also known as is guaranteed elision. If the initializer expression is a prvalue expression of matching type, the prvalue expression is used to directly construct the target of the initialization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With