Re: throwing exceptions from constructor and other alternatives
alfredo.correa@gmail.com wrote:
I don't know, I have mixed fillings now. Many people is saying that
throwing from constructor is totally normal, however how do you think
the resulting syntax will look like?
try{
object construtor
use of object
}catch(...){
object construtor with alternative values
SAME use of object
}
The problem really isn't about throwing from a constructor. As others
have said, throwing from constructors is actually a good thing, because
it lets you write classes which guarantee strong invariants.
The real problem is that exceptions don't mix well with the
retry-and-resume style of error handling. (Exceptions are better
suited to the clean-up-and-fail style.) That's one reason to avoid
using exceptions to signal a "recoverable" error. However, with
constructors, exceptions are really the only way to signal failure
(unless you get into the whole status flag mess, which we want to
avoid.)
So it's often a good idea to avoid designing constructors that have
"re-tryable" failure modes -- perhaps by including the recovery / retry
code in the constructor itself.
But since that's not always possible or desirable, you may need to
adapt a throwing constructor to a retry-and-resume style. You can do
this by wrapping the initialization of the object in a function. In
the following example, the function make_foo() retries the construction
of a foo object until it succeeds.
#include <iostream>
struct foo {
struct bad_i {};
foo( int i ): data(i)
{
if (i < 0) throw bad_i();
}
foo( const foo& rhs ): data( rhs.data )
{
std::cout << "copied!\n";
}
int data;
};
// helper function - wraps the retry loop
foo make_foo( int i )
{
while ( true ) {
try {
return foo(i);
}
catch( const foo::bad_i& ) {
++i; // fix up parameter
}
}
}
int main()
{
foo f1 = make_foo( -3 );
foo f2 = make_foo( -1 );
std::cout << f1.data << ' ' << f2.data << std::endl;
}
The foo copy constructor produces output, so you can tell whether your
compiler applies the RVO to eliminate copying the function return
value. On my compiler, g++ 3.4.2, no copy is made. In effect, we're
using the RVO to "teleport" an object from one scope (inside the try
block inside the function) to another (the scope of main()).
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]