This question is twofold "Constructor with parameter by value and noexcept" . This question showed that the lifecycle management of a function argument by value is handled by the calling function; therefore, the caller handles any exceptions that occur, and the called function can noexcept itself noexcept . I am wondering how the output end is handled using noexcept .
MyType MyFunction( SomeType const &x ) noexcept; //... void MyCaller() { MyType test1 = MyFunction( RandomSomeType() ); MyType test2{ MyFunction( RandomSomeType() ) }; //... test1 = MyFunction( RandomSomeType() ); test2 = std::move( MyFunction(RandomSomeType()) ); MyFunction( RandomSomeType() ); // return value goes to oblivion }
Let's say that the return value was successfully created in MyFunction . And let them say that the corresponding special member functions (copy / move-assign / construction) of MyType may not be noexcept .
- Follow the rules RVO / NRVO / Whatever-from-C ++ 11 regarding the transfer of return values from the called function to the caller, means that the transfer is always not executed, regardless of the
noexcept state of the corresponding special member function? - If the answer to the previous question is “no,” then if the return value is passed, does the exception count against the called function or the caller?
- If the answer to the previous question is “the function being called”, then the usual
noexcept token on MyFunction will call std::terminate . How should the MyFunction noexcept profile be modified? When I asked about this on Usenet, the respondent thought it should be std::is_nothrow_move_assignable<MyType>::value . (Note that MyCaller used several methods for using the return value, but MyFunction does not know which one is used! The answer should cover all cases.) Does it matter if MyType changed to be copyable, but not movable?
So, if the worst cases of the second and third questions are accurate, then any function that returns by value cannot have a simple noexcept if the return type has a noexcept method! Types with moving movements should now be rare, but the template code still needs to "dirty" itself with is_nothrow_move_assignable every time a return-by-value is used.
I think the violation of the function of the called function is violated:
MyType MyFunction( SomeType const &x ) noexcept( ??? ) { //... try { return SOME_EXPRESSION; // What happens if the creation of SOME_EXPRESSION succeeds, but the // move-assignment (or whatever) transferring the result fails? Is // this try/catch triggered? Or is there no place lexically this // function can block a throwing move!? } catch (...) { return MyType(); // Note that even if default-construction doesn't throw, the // move-assignment may throw (again)! Now what? } }
This problem, at least for me, seems to be fixed at the end of the caller (just wrap the move-assignment with try / catch ), but not fixed from the end of the called function. I think the caller should handle this, even if we need to change the C ++ rules for this. Or at least some kind of defect report is required.
source share