Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw exception and return result from a function

I'm just learning C++, and would like to throw an exception, but then the result of my function would be undefined???

 std::vector<myStruct> extract_notworking(std::vector<myStruct>& avec){
        std::vector<myStruct> result;

        if (avec.size() == 0)
            //throw domain_error("Cannot operate on empty vector!");
            //Cannot use exception for it would yield undefined result
            return result;

        //do something here
        //...
        return result;
    }

What should I do? Return an empty vector? What would happen if I threw the exception to the receiver of the return value?

like image 738
Mihaela Avatar asked Mar 03 '12 20:03

Mihaela


People also ask

Can you throw an exception and return a value?

It's not possible to both throw an exception and return a value from a single function call.

Does throwing an exception return the function?

No, because throwing an exception is not a return. If the exception is not handled inside the function it will cause an immediate exit out of the function, passing control to the first point in the program where the exception will be catched ie handled.

How do you return after throwing an exception?

After throwing an exception, you do not need to return because throw returns for you. Throwing will bubble up the call stack to the next exception handler so returning is not required.

Do you need to return after throwing an exception Java?

No, we can not place any code after throw statement, it leads to compile time error Unreachable Statement.


3 Answers

When you throw an exception, the function halts there and execution jumps to wherever the exception was caught. Your function doesn't return anything because the function doesn't return at all.

You can just do

if (avec.empty())
    throw domain_error("Cannot operate on empty vector!");

And your function will exit there.

Note that you don't need to be concerned about the return value ("How can a function not return anything?" etc) because you can't access the return value of a function that threw (and did not catch) an exception even if you try.

So for instance, if you do

try {
    std::vector<myStruct> vec;

    std::vector<myStruct> retval = extract_notworking(vec);

    print_vector(retval); // this line is only executed if extract_networking
                          // does not throw an exception
} catch (const domain_error& e) {
    // we can't access retval here so no worries
}

You can only access retval if the function returns properly (i.e. does not throw). In the example, your function will throw because vec is empty, so print_vector will never be called.

Even if you do this:

std::vector<myStruct> retval;

try {
    std::vector<myStruct> vec;

    retval = extract_notworking(vec);

    print_vector(retval);
} catch (const domain_error& e) {
    // we can access retval here but the assignment never happened
}

Since the function did not return, the assignment of its return value to retval did not happen, and retval is still a perfectly normal default-constructed vector that you can use freely. So in that example, retval is not assigned to and retval is not printed, because extract_networking threw an exception and execution jumped into the catch block before those two things could happen.

like image 77
Seth Carnegie Avatar answered Oct 06 '22 00:10

Seth Carnegie


When you throw an exception, you cannot return, and vice versa. You can think of exceptions as a generalised return designed for exceptional circumstances and errors. Consider this function:

int f(bool b) {
    if (b)
        return 42;
    throw std::runtime_error("Runtime error!");
}

When we call it, we can capture its normal return value (in this case an int) in an expression, or we can capture its exceptional return value (std::runtime_error) using a try block with a catch of the correct type:

try {

    int normal_result = f(b);

    // Use normal result.
    // (Exceptional result does not exist.)
    std::cout << normal_result << '\n';

} catch (const std::exception& exceptional_result) {

    // Use exceptional result.
    // (Normal result does not exist.)
    std::cout << exceptional_result.what() << '\n';

}

The power of exceptions, of course, comes from the fact that they propagate up the call stack until they reach a matching catch. Thus you can use them to escape from deeply nested function calls, while ensuring that your resources (memory, files, &c.) are correctly managed.

like image 37
Jon Purdy Avatar answered Oct 06 '22 00:10

Jon Purdy


What should I do? Return an empty vector? What would happen if I threw the exception to the receiver of the return value?

What is returned from a function is irrelevant, since the return value is not going to be used in any way. The execution will continue at the next catch for that particular exception (off course after unwinding the stack).

like image 24
BЈовић Avatar answered Oct 06 '22 00:10

BЈовић