Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I throw an exception

I am C# programmer but now I want to get more into C++.
I know the basics of C++ but I don't know how to handle errors.

For example: I am writing a library. I create an constructor which requests an integer as an argument.
If that integer is bigger than 50, it is an error. In C# I would throw an ArgumentOutOfRange exception, but what should I do in C++?

like image 746
Florian Avatar asked May 24 '13 11:05

Florian


3 Answers

In C# I would throw an ArgumentOutOfRange exception but what should I do in c++?

First you should consider if that should not be a precondition of your function, leaving the responsibility of checking whether the value is in range to the caller.

If you decide for this option, then invoking the function with an out-of-range value would be undefined behavior, and inside the function you could just have a debug assertion to help you spot possible misuses - without the need of throwing any exception.

If you decide that the function should have a wide contract, on the other hand, and react in a well-defined way by throwing an exception when the argument is outside the permitted range, then you could throw an std::out_of_range exception.

For example: I am writing a libary [...]

If you are writing a library, meaning that you do not know the exact requirements of your clients in terms of performance and robustness, you may consider providing two such functions - one with a wide contract that throws exceptions, and one with a narrow contract that assumes the client provides meaningful input.

This way, the user of your library could decide based on their use cases whether or not it is OK to pay for the overhead of checking the correctness of the input each time your function is called.

This is, for instance, the strategy adopted by the C++ Standard Library for std::vector, which provides a non-throwing operator[] with a narrow contract for accessing elements of the collection based on the index (this function has undefined behavior if the index is out-of-bounds), and a member function at() that performs index checking and throws an exception if the index is out-of-bounds.

like image 104
Andy Prowl Avatar answered Oct 11 '22 19:10

Andy Prowl


It depends on whether an integer larger than 50 could possibly be passed to the constructor as part of normal program flow, or whether that's an exceptional condition. But in general the only way to have object construction fail is by throwing an exception.

Your user code might look like this:

int n = parse_user_input()

if (n < 50)
{
    Foo x(n);
    x.do_cool_stuff();
}
else
{
    // report user error
}

That is, you don't actually use exceptions for normal control flow. With that sort of code pattern, it would be perfectly fine for Foo::Foo(int) to throw an exception if the argument were out of range.

You can find useful standard exception classes in <stdexcept>.

like image 4
Kerrek SB Avatar answered Oct 11 '22 20:10

Kerrek SB


The same thing as in C#: throw an exception. This is the only way to prevent an object from being constructed.

std::invalid_argument is a good standard choice regarding what to throw.

like image 3
Jon Avatar answered Oct 11 '22 18:10

Jon