By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,312 Members | 1,850 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,312 IT Pros & Developers. It's quick & easy.

C++0x/1x exception specifications proposal: Compile-time checked

P: n/a
Perhaps a mechanism can be introduced in the C++0x/1x standard,
something simple like defining a function as:
void somefunc(void) throw()
{
// ...
}
and getting a compile time error saying something like:
"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".

That is make the compiler to check exception specifications for errors too.

Ioannis A. Vranos
Jan 20 '08 #1
Share this Question
Share on Google+
12 Replies


P: n/a
In article <fm***********@ulysses.noc.ntua.gr>,
iv*****@no.spamfreemail.nospam.gr says...
Perhaps a mechanism can be introduced in the C++0x/1x standard,
something simple like defining a function as:

void somefunc(void) throw()
[ ... ]
and getting a compile time error saying something like:

"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".

That is make the compiler to check exception specifications for errors too.
This is next to impossible in practice. In particular, the compiler
doesn't have anything to check against with externally defined functions
-- i.e. you include a header with an exception specification, but the
compiler has no access to the implementation of the "stuff" in that
header (unless it happens to be included inline).

In practice, doing so probably wouldn't be a good idea anyway. Java has
checked exceptions, where the compiler does (more or less) what you're
advocating. Experience has shown (repeatedly) that while this seems like
a good idea, it almost never works well in practice.

In the end, exception specifications are an anti-pattern -- something
that initially seems like a good idea, but in the long run ends up
causing far more problems than it solves.

One of the basic ideas of exception handling is that it sets up more or
less a "tunnel" from the place an exception is thrown to the place it is
caught, and any intermediate layers need not worry about it (beyond
being exception safe). Exception specifications (especially enforced as
you're advocating) require that all intermediate levels DO pay attention
to the exceptions that propagate from the lower levels, though the
intermediate layer has no real interaction with the exception itself at
all. Worse, an intermediate layer might easily work with a function via
a pointer, in which case it simply has no way of knowing what exceptions
might be thrown through it by that function. You could make the
exception specification part of the function signature, so it could only
take pointers to functions that threw from a limited selection of
exceptions, but this would frequently be quite limiting. In many cases,
such call-back functions (and such) haven't even been contemplated when
the code that uses them is written, so it's essentially impossible for
them to even guess at what exceptions they might throw.

In addition, templates and exception specifications are essentially
impossible to blend. A typical template can throw most (if not all) the
exceptions that can be thrown by the type over which it is instantiated
-- but an many cases, nobody has yet imagined the type over which it
will be isntantiated when the template itself is written.

I'll repeat: exception specifications are an anti-pattern. They're
nearly always bad now, and having the compiler attempt to enforce them
would make them even worse.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jan 20 '08 #2

P: n/a
On 2008-01-20 18:13, Ioannis Vranos wrote:
Perhaps a mechanism can be introduced in the C++0x/1x standard,
something simple like defining a function as:
void somefunc(void) throw()
{
// ...
}
and getting a compile time error saying something like:
"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".

That is make the compiler to check exception specifications for errors too.
You might be interested in the following two articles (just a few among
many discussing the subject):

http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!149.entry
http://www.mindview.net/Etc/Discussi...ckedExceptions

--
Erik Wikström
Jan 20 '08 #3

P: n/a
Ioannis Vranos wrote:
Perhaps a mechanism can be introduced in the C++0x/1x standard,
something simple like defining a function as:
void somefunc(void) throw()
{
// ...
}
and getting a compile time error saying something like:
"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".

That is make the compiler to check exception specifications for errors too.

Some more details:
What I have in mind is "loose" application. That is, the compiler should
check only the available code accessible to it.
In addition, I think throw(void) should be equivalent to throw(), and
throw(...) should be equivalent to non-throw specification, e.g.:
// May throw anything.
void somefunc()
{
// ...
}
// May throw anything.
void some func() throw(...)
{
// ...
}
I think that even loose, the compile time checking of throw
specifications will improve the overall exception safety, and everyone
will usually know the exact types of exceptions he can catch on a given
call.
Any existing third-party, pre-built C++ library can be revised to
provide exception specifications at its next release. That is, in the
future the total exception safety will increase, because the exception
specification mechanism will finally work (since now I think it doesn't
work as it is provided, in practice).

Or that library can keep providing its facilities without exception
specifications or with the throw(...) equivalent ones.
If I may repeat, what I have in mind is "loose" application. That is,
the compiler should check only the available code accessible to it.
In the case of some function having the throw() specification, is using
indirectly code that may throw some exception, it can be flagged as a
compile-time error, provided that this source code that is used
indirectly by this function, is accessible to the compiler. Otherwise,
it will not be flagged as a compile-time error.

The run-time stuff of the throw specifications will still apply.
Jan 20 '08 #4

P: n/a
Ioannis Vranos wrote:
Ioannis Vranos wrote:
>Perhaps a mechanism can be introduced in the C++0x/1x standard,
something simple like defining a function as:
void somefunc(void) throw()
{
// ...
}
and getting a compile time error saying something like:
"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".

That is make the compiler to check exception specifications for errors
too.


Some more details:
What I have in mind is "loose" application. That is, the compiler should
check only the available code accessible to it.
In addition, I think throw(void) should be equivalent to throw(), and
throw(...) should be equivalent to non-throw specification, e.g.:
// May throw anything.
void somefunc()
{
// ...
}
// May throw anything.
void some func() throw(...)
{
// ...
}
I think that even loose, the compile time checking of throw
specifications will improve the overall exception safety, and everyone
will usually know the exact types of exceptions he can catch on a given
call.
Any existing third-party, pre-built C++ library can be revised to
provide exception specifications at its next release. That is, in the
future the total exception safety will increase, because the exception
specification mechanism will finally work (since now I think it doesn't
work as it is provided, in practice).

Or that library can keep providing its facilities without exception
specifications or with the throw(...) equivalent ones.
If I may repeat, what I have in mind is "loose" application. That is,
the compiler should check only the available code accessible to it.
In the case of some function having the throw() specification, is using
indirectly code that may throw some exception, it can be flagged as a
compile-time error, provided that this source code that is used
indirectly by this function, is accessible to the compiler. Otherwise,
it will not be flagged as a compile-time error.

The run-time stuff of the throw specifications will still apply.

Addition 2:

In this proposal, I think an opposite of the throw keyword may be
needed, to specify the exceptions that the compiler will ignore. I think
the right place of it, is the end of the function scope. An example:
void somefunc() throw()
{
std::vector<intvec;

// ...

} nothrow(std::out_of_range)

Jan 20 '08 #5

P: n/a
Ioannis Vranos wrote:
Ioannis Vranos wrote:
>Ioannis Vranos wrote:
>>Perhaps a mechanism can be introduced in the C++0x/1x standard,
something simple like defining a function as:
void somefunc(void) throw()
{
// ...
}
and getting a compile time error saying something like:
"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".

That is make the compiler to check exception specifications for
errors too.


Some more details:
What I have in mind is "loose" application. That is, the compiler
should check only the available code accessible to it.
In addition, I think throw(void) should be equivalent to throw(), and
throw(...) should be equivalent to non-throw specification, e.g.:
// May throw anything.
void somefunc()
{
// ...
}
// May throw anything.
void some func() throw(...)
{
// ...
}
I think that even loose, the compile time checking of throw
specifications will improve the overall exception safety, and everyone
will usually know the exact types of exceptions he can catch on a
given call.
Any existing third-party, pre-built C++ library can be revised to
provide exception specifications at its next release. That is, in the
future the total exception safety will increase, because the exception
specification mechanism will finally work (since now I think it
doesn't work as it is provided, in practice).

Or that library can keep providing its facilities without exception
specifications or with the throw(...) equivalent ones.
If I may repeat, what I have in mind is "loose" application. That is,
the compiler should check only the available code accessible to it.
In the case of some function having the throw() specification, is
using indirectly code that may throw some exception, it can be flagged
as a compile-time error, provided that this source code that is used
indirectly by this function, is accessible to the compiler. Otherwise,
it will not be flagged as a compile-time error.

The run-time stuff of the throw specifications will still apply.


Addition 2:

In this proposal, I think an opposite of the throw keyword may be
needed, to specify the exceptions that the compiler will ignore. I think
the right place of it, is the end of the function scope. An example:
void somefunc() throw()
{
std::vector<intvec;

// ...

} nothrow(std::out_of_range)


Some examples of these:
I.

void somefunc() throw(std::bad_alloc, my_app::graph_range_error)
{
// ...
} nothrow(std::out_of_range)

II. Equivalent cases:

void somefunc() throw()
{
// ...
} nothrow(std::bad_alloc)
void somefunc() throw(void)
{
// ...
} nothrow(std::bad_alloc)

III. Equivalent cases:

void somefunc()
{
// ...
}

void somefunc() throw(...)
{
// ...
}

void somefunc() throw(...)
{
// ...
} nothrow()
void somefunc()
{
//...
} nothrow()
void somefunc() throw(...)
{
// ...
} nothrow(void)
void somefunc()
{
//...
} nothrow(void)
Jan 20 '08 #6

P: n/a
Ioannis Vranos wrote:
>
>>>Perhaps a mechanism can be introduced in the C++0x/1x standard,
something simple like defining a function as:
void somefunc(void) throw()
{
// ...
}
and getting a compile time error saying something like:
"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".

That is make the compiler to check exception specifications for
errors too.
Some more details:
What I have in mind is "loose" application. That is, the compiler
should check only the available code accessible to it.
In addition, I think throw(void) should be equivalent to throw(), and
throw(...) should be equivalent to non-throw specification, e.g.:
// May throw anything.
void somefunc()
{
// ...
}
// May throw anything.
void some func() throw(...)
{
// ...
}
I think that even loose, the compile time checking of throw
specifications will improve the overall exception safety, and
everyone will usually know the exact types of exceptions he can catch
on a given call.
Any existing third-party, pre-built C++ library can be revised to
provide exception specifications at its next release. That is, in the
future the total exception safety will increase, because the
exception specification mechanism will finally work (since now I
think it doesn't work as it is provided, in practice).

Or that library can keep providing its facilities without exception
specifications or with the throw(...) equivalent ones.
If I may repeat, what I have in mind is "loose" application. That is,
the compiler should check only the available code accessible to it.
In the case of some function having the throw() specification, is
using indirectly code that may throw some exception, it can be
flagged as a compile-time error, provided that this source code that
is used indirectly by this function, is accessible to the compiler.
Otherwise, it will not be flagged as a compile-time error.

The run-time stuff of the throw specifications will still apply.


Addition 2:

In this proposal, I think an opposite of the throw keyword may be
needed, to specify the exceptions that the compiler will ignore. I
think the right place of it, is the end of the function scope. An
example:
void somefunc() throw()
{
std::vector<intvec;

// ...

} nothrow(std::out_of_range)

Some examples of these:
I.

void somefunc() throw(std::bad_alloc, my_app::graph_range_error)
{
// ...
} nothrow(std::out_of_range)

II. Equivalent cases:

void somefunc() throw()
{
// ...
} nothrow(std::bad_alloc)
void somefunc() throw(void)
{
// ...
} nothrow(std::bad_alloc)

III. Equivalent cases:

void somefunc()
{
// ...
}

void somefunc() throw(...)
{
// ...
}

void somefunc() throw(...)
{
// ...
} nothrow()
void somefunc()
{
//...
} nothrow()
void somefunc() throw(...)
{
// ...
} nothrow(void)
void somefunc()
{
//...
} nothrow(void)

Addition 3:
IV.

// The compiler ignores all exceptions and considers that somefunc()
// will not throw any exception. Thus it will not provide a compile-time
// error.

void somefunc() throw()
{
throw std::bad_alloc();
} nothrow(...)
Jan 21 '08 #7

P: n/a
"Ioannis Vranos" <iv*****@no.spamfreemail.nospam.grwrote in message
news:fm***********@ulysses.noc.ntua.gr...
Perhaps a mechanism can be introduced in the C++0x/1x standard, something
simple like defining a function as:
void somefunc(void) throw()
{
// ...
}
and getting a compile time error saying something like:
"Error: void somefunc(void) throw(): Wrong exception specification.
somefunc can throw std::bad_alloc, std::range_error".
The problem with this is that *any* expression that has the capability of
causing undefined behavior has the capability of throwing any exception. In
particular, this property means that an implementation is permitted to
extend the language so that arithmetic errors, such as division by zero,
throw exceptions.

What would you have such an implementation do about an arithmetic operation
inside a throw() function that might overflow? If the compiler complains
about it, it is rejecting a program that might have nothing wrong with it.
If it doesn't, then you need to figure out how to change your requirement to
permit such behavior.
Jan 21 '08 #8

P: n/a
On 2008-01-20 23:46, Ioannis Vranos wrote:
Ioannis Vranos wrote:
[snip]

Could you please choose one thread for this discussion? Posting the same
thing in multiple threads makes the discussion hard to follow. And it
is a waste of bits :-)

--
Erik Wikström
Jan 21 '08 #9

P: n/a
Erik Wikström wrote:
On 2008-01-20 23:46, Ioannis Vranos wrote:
>Ioannis Vranos wrote:

[snip]

Could you please choose one thread for this discussion? Posting the same
thing in multiple threads makes the discussion hard to follow. And it
is a waste of bits :-)

In my newsgroup reader (Thunderbird) the message appears in the same
discussion thread, with subject "C++0x/1x exception specifications
proposal: Compile-time checked".

Jan 21 '08 #10

P: n/a
On 2008-01-21 21:00, Ioannis Vranos wrote:
Erik Wikström wrote:
>On 2008-01-20 23:46, Ioannis Vranos wrote:
>>Ioannis Vranos wrote:

[snip]

Could you please choose one thread for this discussion? Posting the same
thing in multiple threads makes the discussion hard to follow. And it
is a waste of bits :-)


In my newsgroup reader (Thunderbird) the message appears in the same
discussion thread, with subject "C++0x/1x exception specifications
proposal: Compile-time checked".
In my they do not, the messages are posted both in the thread "Bjarne's
comments about exception specification" and "C++0x/1x exception
specifications proposal: Compile-time checked". Google groups also see
two threads [1]. I notice that you are running Thunderbird 1.5, might be
some bug fixed in later versions.

1.
http://groups.google.com/group/comp....b2f509b3527039
http://groups.google.com/group/comp....b5716c348bae12

--
Erik Wikström
Jan 21 '08 #11

P: n/a
Erik Wikström wrote:
>
>In my newsgroup reader (Thunderbird) the message appears in the same
discussion thread, with subject "C++0x/1x exception specifications
proposal: Compile-time checked".

In my they do not, the messages are posted both in the thread "Bjarne's
comments about exception specification" and "C++0x/1x exception
specifications proposal: Compile-time checked". Google groups also see
two threads [1]. I notice that you are running Thunderbird 1.5, might be
some bug fixed in later versions.

1.
http://groups.google.com/group/comp....b2f509b3527039
http://groups.google.com/group/comp....b5716c348bae12

No, you are right on this. I indeed opened a new specific discussion
thread about my proposal so as to gather more feedback.

Jan 21 '08 #12

P: n/a
Ioannis Vranos wrote:
>
The solution that I propose on this, is the keyword :exceptions or
:_exceptions:
void somefunc2() _throw(graph_exception)
{
throw graph_exception();
}
void somefunc1() _throw(time_exception)
{

somefunc2();

throw time_exception();

} _nothrow(std::out_of_range)
int main()
{
somefunc1() :exceptions;
}

at compile-time it will produce a compiler message, something like:

"main()::somefunc1() may throw exceptions:
somefunc1()::somefunc2()::graph_exception, somefunc1::time_exception".
After we write our exception handlers, we can remove the keyword
":exceptions" from somefunc1(); statement in main(), and thus main becomes:
void somefunc2() _throw(graph_exception)
{
throw graph_exception();
}
void somefunc1() _throw(time_exception)
{

somefunc2();

throw time_exception();

} _nothrow(std::out_of_range)
int main() try
{
somefunc1();
}
catch(graph_exception)
{
// ...
}
catch(time_exception)
{
// ...
}


Compiler checks/errors:
Where the source code is available to the compiler, any
_nothrow(some_exception) specification at a function/member function,
must have at least one equivalent catch(some_exception) or catch(...)
exception handler at the function definition.

For example:
void somefunc() _throw()
{
int *p= new int[10];

} _nothrow (std::bad_alloc)
should be flagged as a compiler error, because there is no
catch(std::bad_alloc) or catch(...) exception handler at the function
definition.
The following should be correct:
1 .

void somefunc() try _throw()
{
int *p= new int[10]

} _nothrow (std::bad_alloc)
catch(std::bad_alloc)
{
// ...
}
2.

void somefunc() try _throw()
{
int *p= new int[10]

} _nothrow (std::bad_alloc)
catch(...)
{
// ...
}
3.

void somefunc() try _throw()
{
int *p= new int[10]

} _nothrow (...)
catch(...)
{
// ...
}
Jan 22 '08 #13

This discussion thread is closed

Replies have been disabled for this discussion.