Jagan Arikuti
Jagan Arikuti

Reputation: 385

Return statement in a handler of function-try-block of a constructor

Please help with an example to understand below

From C++ n45277 : $15.3 - 13

If a return statement appears in a handler of the function-try-block of a constructor, the program is ill-formed.

does this mean using return in constructor ??

Thanks

Upvotes: 4

Views: 764

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596672

A function-try-block is a try block that wraps outside the entire body of a function or constructor, rather than just a section of code inside of the body.

In the case of a constructor, it allows you to catch an exception that is thrown while initializing base classes and data members within the initialization list. If such an exception is thrown, you can catch it and process the error as needed, but you cannot return from the catch block. When execution reaches the end of the catch block, the current exception is automatically rethrown. Before the catch is entered, any base class and data member that was successfully constructed before the initial exception was thrown has already been destructed to prevent leaks.

As the standard says:

If a return statement appears in a handler of the function-try-block of a constructor, the program is ill-formed.

In this case, the handler is referring to a catch block of the try block.

For example:

int checkValue(int value)
{
    if (value == 1)
        throw std::runtime_error("illegal value");
    return value;
}

struct A
{
    std::string str;
    int value;

    A(int i) try : str("hello"), value(checkValue(i))
    {
        // constructor body here ...
        // 'return' is OK here!
    }
    catch (...)
    {
        // do something here (log the error, etc)...
        // 'return' is illegal here!
    }
};

Notice how the try is before the initialization list, and the body of the constructor is inside of the try block.

If checkValue() throws an exception, the construction of A is aborted, automatically destructing str in the process.

You could accomplish the same thing without using a function-try-block:

int checkValue(int value)
{
    if (value == 1)
        throw std::runtime_error("illegal value");
    return value;
}

struct A
{
    std::string str;
    int value;

    A(int i)
    {
        try
        {
            str = "hello";
            value = checkValue(i);
            // 'return' is OK here!
        }
        catch (...)
        {
            // do something here (log the error, etc)...
            // 'return' is OK here! But then the constructor
            // would not be aborted...
            throw;
        }
    }
};

Where function-try-block is commonly used is when you want to catch/log exceptions that are thrown in things that cannot be invoked inside the normal constructor body, only in the initialization list, such as base class constructors and data member constructors.

Upvotes: 3

Related Questions