In which case a function / method is guarantee not to throw anexception ?

R

Roberto Giaffy

I want to understand if sometime it is possible to be sure
a function / method will never throw an exception;

I think a function / method that only perform assignment / copy
operation on primitive types like int, bool, double etc., then
it is guarantee it will never throw an exception
so it can be qualified with "throw()"

(Note: just at this very beginning, I do not want to ask
if it is a good practice such a qualifying, just suppose
it is already present in some old library)

But I wonder if a class containing basic type (or also
other class containing basic types) can be manipulated
and the function / method can still offering a no-throw guarantee;

an example:

// a class of only basic types
class A {

int i;
double j;
bool k;

public:
A() : i(0), j(0), k(0) {};

A( int I, doule J, bool K ) : i(I), j(J), k(K) {};
};

// a function that call constructor,
// copy constructor, copy operator and
// create a temporary object A
A afunction( int i, double j, bool k) throw()
{
A a( i, j, k);

A b= a;

A c;

c= b;

return( A( i, j ,k) );
}

It will be correct the fun. afunction() will never throw ? or I am
missing
some fundamental point ?

thanks
Giaffy
 
I

Ian Collins

I want to understand if sometime it is possible to be sure
a function / method will never throw an exception;

I think a function / method that only perform assignment / copy
operation on primitive types like int, bool, double etc., then
it is guarantee it will never throw an exception
so it can be qualified with "throw()"

(Note: just at this very beginning, I do not want to ask
if it is a good practice such a qualifying, just suppose
it is already present in some old library)

But I wonder if a class containing basic type (or also
other class containing basic types) can be manipulated
and the function / method can still offering a no-throw guarantee;

Yes, there's nothing there that can throw!
 
J

Joshua Maurice

I want to understand if sometime it is possible to be sure
a function / method will never throw an exception;

I think a function / method that only perform assignment / copy
operation on primitive types like int, bool, double etc., then
it is guarantee it will never throw an exception
so it can be qualified with "throw()"

(Note: just at this very beginning, I do not want to ask
if it is a good practice such a qualifying, just suppose
it is already present in some old library)

But I wonder if a class containing basic type (or also
other class containing basic types) can be manipulated
and the function / method can still offering a no-throw guarantee;

an example:

// a class of only basic types
class A {

 int i;
 double j;
 bool k;

public:
 A() : i(0), j(0), k(0) {};

 A( int I, doule J, bool K ) : i(I), j(J), k(K) {};
 };

// a function that call constructor,
// copy constructor, copy operator and
// create a temporary object A
 A afunction( int i, double j, bool k) throw()
 {
    A a( i, j, k);

    A b= a;

    A c;

    c= b;

    return( A( i, j ,k) );
 }

It will be correct the fun. afunction() will never throw ? or I am
missing
some fundamental point ?

The fundamental point is that in standard C++, exceptions are not
thrown from thin air. Operations on primitives do not throw, where
primitives are things like the integers, characters, pointers.
Operations on simple structs and classes of only primitives
(collectively known as POD types, using this informal definition) do
not throw. The only things which can throw are a "throw" statement,
dynamic_cast on a reference type, standard library functions and
standard language features and functions which are documented as can
throw an exception (most prominently operator new), and any function
which directly or indirectly does any of those things. (I might be
missing some other thing which can throw. It's late, and I can't
recall off the top of my head.) Your code has none of those things
which can throw, so your code does not throw.
 
R

Roberto Giaffy

Hi Ian,
thanks for the answer;

I tried to look at the C++ spec. but I did not find a
section where it is clarified what/when en exception can
be thrown;

Can you point me where to look for info (if any) to build such a
cases ?
Or all the possible cases are indirectly connected to the new() oper.
allocation that could fail ?

thanks
Giaffy
 
R

Roberto Giaffy

Thank again for the answer;
so the list for determining what/when something could throw an
exception
could start with:
1 - "throw()" statement;
2 - dynamic_cast on a reference type
3 - standard library functions (documented as throwing)
4 - standard language features and functions (prominently operator
new());

I think the 4th point is the one I should investigate more;
I will probably look at the C++ standard, specifically at the new()
operator;
also is there any other suggestion that can help me on where to look
for such details?

Note: the code provided in the 2st post was just an example, I would
like to
understand when a method/function can be qualified with throw() - a no-
throwing function;

thanks again,
Giaffy
 
J

James Kanze

I tried to look at the C++ spec. but I did not find a
section where it is clarified what/when en exception can
be thrown;

At the language level, there are only two things that can
possibly cause an exception to be thrown: a throw expression,
and undefined behavior (which, of course, can do absolutely
anything). At the library level, in practice, I would assume
that any function which doesn't specifically document that it
cannot throw might.
Can you point me where to look for info (if any) to build such
a cases ?
Or all the possible cases are indirectly connected to the
new() oper. allocation that could fail ?

The new operator itself cannot throw. It does, however, call
functions which are, in some cases, documented to possibly
throw.

For most of the standard library, however, there is a vague
clause to the effect that any function can throw anything it
wants, for any reason it feels like. (And of course, exceeding
the resource limits of your system causes undefined behavior, so
who knows what might happen.)
 
J

Joshua Maurice

At the language level, there are only two things that can
possibly cause an exception to be thrown: a throw expression,
and undefined behavior (which, of course, can do absolutely
anything).  

At least 3 things. You missed dynamic_cast on a reference type when
the cast fails, such as
dynamic_cast<T&>(x);
when x is "not a" T. I did just mention this else-thread.
 
T

tonydee

Thank again for the answer;
so the list for determining what/when something could throw an
exception
could start with:
 1 - "throw()" statement;
 2 - dynamic_cast on a reference type
 3 - standard library functions (documented as throwing)

James Kanze said elsethread:
At the library level, in practice, I would assume
that any function which doesn't specifically document that it
cannot throw might.

I generally assume what I tend to think of as "C functions" will not
throw - by which I mean things like strcmp, isalnum etc. - although I
guess an implementation would be free to have some C++-specific checks/
throws #ifdef-ed in for precondition violations....


 4 - standard language features and functions (prominently operator
new());

I think the 4th point is the one I should investigate more;
I will probably look at the C++ standard, specifically at the new()
operator;
also is there any other suggestion that can help me on where to look
for such details?

Note: the code provided in the 2st post was just an example, I would
like to
understand when a method/function can be qualified with throw() - a no-
throwing function;

It really is just a matter of knowing that any potentially-throwing
code beneath it already has catch() blocks. Still, the only good
reason I've seen for throw() was on an old Sun C++ where some
functions wouldn't inline without it.

Cheers,
Tony
 
M

Michael Doubez

James Kanze said elsethread:


I generally assume what I tend to think of as "C functions" will not
throw - by which I mean things like strcmp, isalnum etc. - although I
guess an implementation would be free to have some C++-specific checks/
throws #ifdef-ed in for precondition violations....




It really is just a matter of knowing that any potentially-throwing
code beneath it already has catch() blocks.  Still, the only good
reason I've seen for throw() was on an old Sun C++ where some
functions wouldn't inline without it.

From Herb Sutter: http://www.gotw.ca/publications/mill22.htm
"Boost’s experience is that a throws-nothing specification on a non-
inline function is the only place where an exception specification
“may have some benefit with some compilers” [...]"

I have also seen people claim that throw() specification causes a
slowdown because of runtime checks for calling unexpected() but I have
no source backing that (and it seems from the same article that the
check is not done at least on VC7).
 
T

tonydee

[...]Still, the only good
reason I've seen for throw() was on an old Sun C++ where some
functions wouldn't inline without it.

From Herb Sutter:http://www.gotw.ca/publications/mill22.htm
"Boost’s experience is that a throws-nothing specification on a non-
inline function is the only place where an exception specification
“may have some benefit with some compilers” [...]"

Well, I'm not going to dig around for old Sun compilers just to prove
it to you, or Herb ;-P.

Cheers,
Tony
 
I

Ian Collins

It really is just a matter of knowing that any potentially-throwing
code beneath it already has catch() blocks. Still, the only good
reason I've seen for throw() was on an old Sun C++ where some
functions wouldn't inline without it.

Odd, I've used every version of Sun CC and I haven't come across that one.
 
J

James Kanze

Leigh Johnston wrote:

[...]
Especially when you're not. James made it clear that he was
giving additional details on how allocation works, and what he
said was absolutely correct and to the point.

There's no right or wrong about it. A new expression can
certainly result in an exception being thrown. As can just
about any other function call. The point I was trying to make,
perhaps somewhat awkwardly, was that exceptions don't just
happen; they are always the result of a throw exception. (Which
isn't quite right, since there are a few other
cases---dynamic_cast of a reference, for example.) And a
function (called explicitly or implicitly) will only raise an
exception if it explicitly calls throw: it's not the new
operator which throws, but one of the functions (operator new or
the constructor) which it implicitly calls.

Beyond that, I'm not too sure what the original poster is
looking for. Ideally, all functions would be documented with
regards to the exceptions they might throw; practically, that's
not really practical if the function calls other functions,
which call other functions, etc. So it's best to assume that a
function can throw anything, unless it's documented otherwise.
And of course, according to the standard, a function in the
standard can throw just about anything it pleases, for whatever
reasons it pleases.

This is, IMHO, a defect in the standard. Which I don't expect
implementers to take advantage of: the day std::string::size()
throws a double, I'll complain loudly, even if the standard says
that it's conforming. In practice, the only compiler I know
that throws anything that isn't required by the standard is
VC++, and then only if you compile with /EHa rather than /EHs.
 
J

James Kanze

James Kanze said elsethread:
I generally assume what I tend to think of as "C functions"
will not throw - by which I mean things like strcmp, isalnum
etc. - although I guess an implementation would be free to
have some C++-specific checks/ throws #ifdef-ed in for
precondition violations....

Good point. I could, I suppose, beg off by saying that the fact
that they can be called from C is implicit documentation that
they cannot throw (with the exception of those which use a
callback, like qsort and bsearch). Although technically: all
that is required of the C library functions in C++ is that they
have the correct behavior. There's nothing to prevent a C++
compiler from coming with its own implementations, 100% C++.
(As far as I know, the only restriction is that the
implementation of malloc cannot use std::eek:perator new. Still, I
tend to assume that other functions in the C library won't use
C++ functionality either: my implementation of a debugging
operator new uses memcpy and memcmp, for example, and if one of
those calls operator new, I'll end up with an endless
recursion.)

[...]
It really is just a matter of knowing that any
potentially-throwing code beneath it already has catch()
blocks. Still, the only good reason I've seen for throw() was
on an old Sun C++ where some functions wouldn't inline without
it.

An empty expression specification (throw()) is an important
guarantee. It's impossible to write exception safe code without
it.
 
A

Alf P. Steinbach

* James Kanze:
This is, IMHO, a defect in the standard. Which I don't expect
implementers to take advantage of: the day std::string::size()
throws a double, I'll complain loudly, even if the standard says
that it's conforming. In practice, the only compiler I know
that throws anything that isn't required by the standard is
VC++, and then only if you compile with /EHa rather than /EHs.

About ten+ years ago the Lotus Notes API used to throw integers; I don't know if
it still does but probably it does.

And of course Microsoft's MFC liked to throw pointers to exception objects.

To deal with that kind of mess, at the time I advocated "exception translation"
by using a single catch(...) and a function rethrowing the exception, catching
all the known types, and rethrowing as a std::runtime_error derived exception.

My colleagues thought this was pretty stupid because (1) it was too darn clever
(never mind the paradoxical nature of that argument, "clever" in software =
bad), and (2) MSVC 6.0 had a bug where it didn't properly call destructors when
exceptions were involved, I don't recall the details exactly but it was bad.

Perhaps today compiler conformance & programmer education has advanced to a
point where the exception translation scheme is practical for real-world code?
Perhaps it would be nice with some "standard" support for such translation --
e.g. in the Boost library? Of course, keeping the usage simple (which is the
whole point of the scheme) might be difficult with Boost...


Cheers,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top