Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is prvalue elision allowed in throw expressions

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?

like image 566
Curious Avatar asked Aug 27 '18 23:08

Curious


1 Answers

From a recent draft standard

11.6 [dcl.init]/15

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:

11.6 [dcl.init]/17.6.1

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.

like image 186
Yakk - Adam Nevraumont Avatar answered Nov 15 '22 08:11

Yakk - Adam Nevraumont