Who manages the exception thrown by a copy constructor in parameters? [duplicate]
Asked Answered
B

2

5

Assume I have this function

void foo() noexcept
{
   // Safely noexcept code.
}

And then this class:

class Bar
{
   Bar(const Bar&) { ... } // Is not noexcept, so might throw
   // Non movable:
   Bar(Bar&&) = delete;
};

Now, I need to modify foo() to receive a Bar by value:

void foo(Bar bar) // noexcept?
{
   // Safely noexcept code
}

I assume the copy of Bar is done before the call to foo, so the code of foo could theoretically still be noexcept, but I am not sure how is that at C++ level defined. Does foo need to get the noexcept deleted or is the caller who might throw when coping Bar? Does it depend on the call mode(stdcall, farcall, etc..) or compiler? Update: In other questions I did not found any reference to the call convention. That should make a difference on the behavior. I supose.

Bewhiskered answered 20/9, 2019 at 15:50 Comment(2)
foo could stay noexcept. copy (if any) happens before the call.Skippet
@jarod42 but wouldnt that depend on the calling convention from the compiler?Bewhiskered
C
3

See [expr.call]/4:

The initialization and destruction of each parameter occurs within the context of the calling function. [ Example: The access of the constructor, conversion functions or destructor is checked at the point of call in the calling function. If a constructor or destructor for a function parameter throws an exception, the search for a handler starts in the scope of the calling function; in particular, if the function called has a function-try-block (Clause 18) with a handler that could handle the exception, this handler is not considered. —end example ]

Therefore you can still mark foo noexcept, even though the initialization of bar might throw. The calling function should not be noexcept. (That is, unless you're ok with the program being terminated in case of an exception.)

Citrine answered 20/9, 2019 at 16:0 Comment(3)
How is it with the initialization of return values?Harker
I'd add one more note that even the evaluation of default parameters happens in the caller contextTechnics
@DanielLangr That should be asked as a new question.Citrine
T
0

The construction of the parameters happens in the caller; once all parameters have been built/converted the function is called.

Something that may not be obvious is that in C++ even default value expression for non-passed parameters happens in the caller: i.e.

void foo(MyClass x=MyClass()) {
    ...
}

the construction in case of

foo();

is still done at the caller site, before the function is actually called.

Technics answered 20/9, 2019 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.