473,513 Members | 2,708 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Separating scope of try block?

Is there a way (idiom, construct, anything like that) to divorce the
scope of a try block from the region of code where it will catch the
exception? I mean, suppose I have a code snippet like this:

try {
Object o("data", 25, 16384);
o.process(); // This may throw, but I don't want to handle it here.
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
}

Now, suppose the construction of o could fail with an exception, which
is why we put it inside a try block. If this happens, we want to do
something to handle it (in this case, notify the user and move on). But
after it's constructed, we want to do something else with the object,
and this stuff could also fail. But if it does, we want the exception
to propagate outward to the surrounding handlers.

Is there a way to trap exceptions from a constructor and not trap
exceptions in the subsequent processing of the object?
Apr 4 '06 #1
14 1640
Adam H. Peterson wrote:
Is there a way (idiom, construct, anything like that) to divorce the
scope of a try block from the region of code where it will catch the
exception? I mean, suppose I have a code snippet like this:

try {
Object o("data", 25, 16384);
o.process(); // This may throw, but I don't want to handle it here.
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
}

Now, suppose the construction of o could fail with an exception, which
is why we put it inside a try block. If this happens, we want to do
something to handle it (in this case, notify the user and move on). But
after it's constructed, we want to do something else with the object,
and this stuff could also fail. But if it does, we want the exception
to propagate outward to the surrounding handlers.

Is there a way to trap exceptions from a constructor and not trap
exceptions in the subsequent processing of the object?


Throw a different exception.

--
Ian Collins.
Apr 4 '06 #2
Adam H. Peterson wrote:

bool oIsConstructed = false;
try {
Object o("data", 25, 16384);
oIsConstructed = true;
o.process(); // This may throw, but I don't want to handle it here.
} catch (...) {
Always catch by name. ... is a hack that's only useful for debugging.

if (oIsConstructed) throw;
std::cerr << "Couldn't construct the object" << std::endl;
}


You were thinking too far inside the box. try catch is useful because our
original old-fashioned techniques still also work.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 5 '06 #3
Ian Collins wrote:
Throw a different exception.


And note my post didn't think outside that box, either.

Use my technique only if you can't change the source to Object, or if its
constructor is deep and you don't know what it will throw.

Alternately, put a try-catch block around the inside of the constructor
(there's a special syntax for that), catch whatever it throws, and rethrow
as Ian's special exception.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 5 '06 #4
Phlip wrote:
Adam H. Peterson wrote:
} catch (...) {

Always catch by name. ... is a hack that's only useful for debugging.


The ellipsis was just to simplify the question. I didn't want answers
directed towards exception translation or special casing, which I
thought some might suggest if I named the exception. And, in
"pseudo-code style," a reader could interpret the ellipsis as "whatever
you want here."

But the point is still good.

if (oIsConstructed) throw;

std::cerr << "Couldn't construct the object" << std::endl;
}

You were thinking too far inside the box. try catch is useful because our
original old-fashioned techniques still also work.


Thanks. I do tend to want language features to handle such complexity
ad absurdium, and it's good to get a reminder that old-and-simple still
usually works. This idiom appears to me to do what I want, and I can't
think of a situation where it would be non-applicable.
Apr 5 '06 #5
Adam H. Peterson wrote:
Is there a way (idiom, construct, anything like that) to divorce the
scope of a try block from the region of code where it will catch the
exception? I mean, suppose I have a code snippet like this:

try {
Object o("data", 25, 16384);
o.process(); // This may throw, but I don't want to handle it here.
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
}


The first thing that comes to mind is a nested try..catch:

try {
Object o("data", 25, 16384);
try {
o.process();
} catch (...) {
std::cerr << "Couldn't process the object" << std::endl;
}
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
}

Or, If your object has a defualt constructor and an operator=, you
could write it like this:

Object o;
try {
o = Object("data", 25, 16384); // Ugly; calls CTOR and operator=
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
return;
}
try {
o.process();
} catch (...) {
std::cerr << "Couldn't process the object" << std::endl;
}

Of course, my personal favorite would be to use a shared pointer; then
you wouldn't need to add a default ctor and an operator=. It would
look like this:

shared_ptr<Object> o;
try {
o.reset(new Object("data", 25, 16384));
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
return;
}
try {
o->process();
} catch (...) {
std::cerr << "Couldn't process the object" << std::endl;
}

Apr 5 '06 #6
>The first thing that comes to mind is a nested try..catch:

try {
Object o("data", 25, 16384);
try {
o.process();
} catch (...) {
std::cerr << "Couldn't process the object" << std::endl;
}
} catch (...) {

std::cerr << "Couldn't construct the object" << std::endl;

}
Yeah, I don't care for this one because I want the exception(s) to
propagate unless they're in the constructor. One of the big wins for
exceptions is their ability to consolidate handling code and allow the
handling policy to be global.
Or, If your object has a defualt constructor and an operator=, you
could write it like this:

Object o;
try {
o = Object("data", 25, 16384); // Ugly; calls CTOR and operator=
} catch (...) {

std::cerr << "Couldn't construct the object" << std::endl;
return;
}

try {
o.process();
} catch (...) {

std::cerr << "Couldn't process the object" << std::endl;

}
A bit inelegant, but it would do the job if you have a qualifying
object and "return" will take you to the right place. I don't like the
inefficiency of avoidable assignment, but I guess it would serve in a
pinch.
Of course, my personal favorite would be to use a shared pointer; then
you wouldn't need to add a default ctor and an operator=. It would
look like this:

shared_ptr<Object> o;
try {
o.reset(new Object("data", 25, 16384));
} catch (...) {

std::cerr << "Couldn't construct the object" << std::endl;
return;
}

try {
o->process();
} catch (...) {

std::cerr << "Couldn't process the object" << std::endl;

}


I must confess I like this one least of all, as it involves using the
heap. This introduces both inefficiency and the possibility of
throwing on memory allocation.

Thanks for the suggestions, though. I like the solution Philip
provided best.

Apr 5 '06 #7

Adam H. Peterson wrote:
Thanks for the suggestions, though. I like the solution Philip
provided best.


What's wrong with something like this instead?

try
{
Object o("data", 25, 16384);
o.process();
}
catch( MyProcessException &e )
{
std::cerr << "Couldn't process the object" << std::endl;
}
catch(...)
{
// Something else happened (constructor threw?) - pass it on
throw;
}

Depending on what exactly you want to do, you may even be able to ommit
the last catch block.

Cheers,
Andre

Apr 5 '06 #8

Adam H. Peterson wrote:
Thanks for the suggestions, though. I like the solution Philip
provided best.


Did you see Phlip's reply to Ian Collins's suggestion?

Unless there's some reason you can't be sure which exception will be
thrown and you have to catch(...) (which isn't nice), or the two
operations you are trying to distinguish between (constructing the
Object and calling process on the Object) indicate failure by throwing
the same type of exception (also not nice, since they seem like
conceptually very different failures) then just use throw different
exception types for different circumstances and catch only the types
you can handle at each level.

Gavin Deane

Apr 5 '06 #9
> Did you see Phlip's reply to Ian Collins's suggestion?

Yes, I saw it. I am addressing the second of your situations, but it
happens to handle the first as well. Specifically, I know what the
constructor might throw and I know how I want to handle it. But for
all I know, the rest of the processing might throw the same exception
type and if so I don't want to handle it locally -- that's an
unanticipated condition (within this block at least). So far Philip's
solution fits what I want to do best. Ian's doesn't work, because it's
not actually the constructor throwing the exception, it's one of the
functions calling it. And I don't want to do exception translation
because that just looks awkward when Philip's solution does the job so
nicely.

Apr 5 '06 #10
>What's wrong with something like this instead?

try
{
Object o("data", 25, 16384);
o.process();
}

catch( MyProcessException &e )
{
std::cerr << "Couldn't process the object" << std::endl;
}

catch(...)
{
// Something else happened (constructor threw?) - pass it on
throw;

}


Alas, the second catch block is purely redundant. And in this case,
the MyProcessException will be handled locally whether Object() throws
it or process() throws it. (Of course, I already knew how to do that.)

Apr 5 '06 #11
> And I don't want to do exception translation
because that just looks awkward when Philip's solution does the job so
nicely.


More accurately, exception translation won't work in my case.
process() happens to be a callback and Object is in a library I'm
working on. Because process() is user supplied code, I don't know
whether it will be instancing Objects of its own, and exception
translation would still have both Object() and process() throwing the
same exception.

Apr 5 '06 #12

Phlip wrote in message <1_*******************@newssvr30.news.prodigy.com> ...

Alternately, put a try-catch block around the inside of the constructor
(there's a special syntax for that), catch whatever it throws, and rethrow
as Ian's special exception.

"Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
(available for free here. You can buy it in hardcopy too.):
http://www.mindview.net/Books/TICPP/...ngInCPP2e.html

Chapter 1, "InitExcept.cpp" may be an example of 'that'.

--
Bob R
POVrookie
Apr 5 '06 #13
Adam H. Peterson wrote:
Is there a way (idiom, construct, anything like that) to divorce the
scope of a try block from the region of code where it will catch the
exception? I mean, suppose I have a code snippet like this:

try {
Object o("data", 25, 16384);
o.process(); // This may throw, but I don't want to handle it here.
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
}
[ snip ]
Is there a way to trap exceptions from a constructor and not trap
exceptions in the subsequent processing of the object?


Object *ptr = 0;

// trap construction exceptions, turning them into null pointer
try {
ptr = new Object("data", 25, 16384);
} catch (...) {
std::cerr << "Couldn't construct the object" << std::endl;
}

// If the object was made, process it without trapping exceptions.
if (ptr != 0) {
// process object: exceptions not trapped
}

// Finally, done with object, blow it away
delete ptr;

You can't get around dynamic allocation of the object, because if you
construct the object in the lexical scope of the try in automatic
storage, it will be destroyed when the try block finishes. Yet you want
to keep the object around, so you can process it outside of the
exception-handling region.

Apr 6 '06 #14
Adam H. Peterson wrote:
Is there a way (idiom, construct, anything like that) to divorce the
scope of a try block from the region of code where it will catch the
exception?


std::auto_ptr<Object> optr;

try {
optr.reset( new Object(x) );
}
catch(...) {
// handle error
}

Object &o = *optr.get();

// do stuff with o, and don't mention optr again

Apr 6 '06 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
3136
by: pembed2003 | last post by:
Hi all, I am reading the book "C++ How to Program" and in the chapter where it discuss scope rule, it says there are four scopes for a variable: function scope file scope block scope...
18
3423
by: Minti | last post by:
I was reading some text and I came across the following snippet switch('5') { int x = 123; case '5': printf("The value of x %d\n", x); break; }
5
2070
by: pembed2003 | last post by:
Hi all, I am reading the book "C How to Program" and in the chapter where it discuss scope rule, it says there are four scopes for a variable: function scope file scope block scope...
17
2298
by: Joe Laughlin | last post by:
I've not used C much before, so I don't know how robust or good this code is. I'd appreciate any feedback or criticisms anyone has! Thanks, Joe #include <stdio.h> #include <string.h>
8
3358
by: TTroy | last post by:
I have a few questions about "scope" and "visibility," which seem like two different things. To me "visibility" of the name of a function or object is the actual code that can use it in an...
7
2164
by: Christian Christmann | last post by:
Hi, I've a a question on the specifier extern. Code example: void func( void ) { extern int e; //...
1
25621
pbmods
by: pbmods | last post by:
VARIABLE SCOPE IN JAVASCRIPT LEVEL: BEGINNER/INTERMEDIATE (INTERMEDIATE STUFF IN ) PREREQS: VARIABLES First off, what the heck is 'scope' (the kind that doesn't help kill the germs that cause...
8
4518
by: Erik de Castro Lopo | last post by:
Hi all, Consider the following code snippet: do { int r = rand () ; } while (r != 0) ; It seems the compiler I'm using (GCC) does realise that the
1
3742
by: Giacomo Catenazzi | last post by:
Hello, To learn the details of C, I've build the following example, could you check if it is correct and if it miss some important cases? Are there some useful (real cases) examples of: -...
0
7380
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7535
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7098
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7523
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
5085
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4745
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3232
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3221
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1592
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.