From: DeMarcus on
The debate about dynamically or statically checked exceptions will never
end. Still, I would like to propose a compromise.

Can we have a flag in the compiler that, when set, will do a static
check for throw(), i.e. no-throw functions?

That would help a lot when trying to write exception safe code with
guarantees [1][2].

[1] http://en.wikipedia.org/wiki/Exception_guarantees
[2] http://www.boost.org/community/exception_safety.html


Regards,
Daniel


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Feb 3, 12:34 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> The debate about dynamically or statically checked exceptions will never
> end. Still, I would like to propose a compromise.
>
> Can we have a flag in the compiler that, when set, will do a static
> check for throw(), i.e. no-throw functions?
>
> That would help a lot when trying to write exception safe code with
> guarantees [1][2].
>
> [1]http://en.wikipedia.org/wiki/Exception_guarantees
> [2]http://www.boost.org/community/exception_safety.html

Well, it certainly would. However...

1. That's IMO really hard to do in practice. In calls to existing code
without source, compiler has no idea whether it will throw or not,
unless it's compiled with same flags. Then, innocuous calls like
operator new can be overriden to throw or not, at runtime. that would
be impossible to detect.

2. often, a no-throw guarantee is not at the function boundary, but
rather just a couple of lines in an existing one. So that makes your
idea not-far-reaching-enough (e.g. something like "nothrow {}" would
be even more useful. For example, recently someone asked here "what if
creation of scope guard throws" and the answer to that is "your job to
make sure it does not"; no-one in their right mind would put scope
guard creation in a function.


Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: DeMarcus on
Goran wrote:
> On Feb 3, 12:34 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
>> The debate about dynamically or statically checked exceptions will never
>> end. Still, I would like to propose a compromise.
>>
>> Can we have a flag in the compiler that, when set, will do a static
>> check for throw(), i.e. no-throw functions?
>>
>> That would help a lot when trying to write exception safe code with
>> guarantees [1][2].
>>
>> [1]http://en.wikipedia.org/wiki/Exception_guarantees
>> [2]http://www.boost.org/community/exception_safety.html
>
> Well, it certainly would. However...
>

Thanks Goran! You gave me perfect feedback. Look here:

> 1. That's IMO really hard to do in practice. In calls to existing code
> without source, compiler has no idea whether it will throw or not,
> unless it's compiled with same flags. Then, innocuous calls like
> operator new can be overriden to throw or not, at runtime. that would
> be impossible to detect.
>

Yes, you are completely right. However, the idea is that the compiler
flag should only give a warning, and only when set. Therefore, when the
compiler gives me a warning about someFunction() throw() that uses
another function without throw(), I can choose to embrace it with
try/catch(...). Now I now that at least someFunction() won't throw and
crash on me when the exception reaches the caller that "must never throw".

This way we can make the our own code provide complete no-throw
guarantees, but not without help from the compiler's warnings.

> 2. often, a no-throw guarantee is not at the function boundary, but
> rather just a couple of lines in an existing one. So that makes your
> idea not-far-reaching-enough (e.g. something like "nothrow {}" would
> be even more useful. For example, recently someone asked here "what if
> creation of scope guard throws" and the answer to that is "your job to
> make sure it does not"; no-one in their right mind would put scope
> guard creation in a function.
>

I think that particular someone was me. ;) I try understand all this
about exception safety, so please excuse my lack of experience.
Anyway, you write "your job is to make sure it does not" (throw). It is
my job, yes, but if the compiler could do the job for me, or at least
warn about a potential meltdown, my job would so much less stressful.

Let's take a good example. Nowhere can I find proper documentation
whether std::vector's pop_back() throws or not. On the contrary, if we
look at the synopsis for boost::shared_ptr
(http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm)
we see that most functions are documented with "// never throws"
How do we know that? Just because they write it? Or do they actually do
a try/catch(...) in the code, and if so, why not declare those functions
with throw()?

When you write "your job is to make sure it does not" (throw), I claim
that with the lack of documentation and compiler help, this is not an
easy task!


You also write "no-one in their right mind would put scope guard
creation in a function". I don't think I understand what you meant. I
would appreciate if you explained that.

Thanks,
Daniel


>
> Goran.
>
>


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Feb 4, 9:41 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> > 1. That's IMO really hard to do in practice. In calls to existing code
> > without source, compiler has no idea whether it will throw or not,
> > unless it's compiled with same flags. Then, innocuous calls like
> > operator new can be overriden to throw or not, at runtime. that would
> > be impossible to detect.
>
> Yes, you are completely right. However, the idea is that the compiler
> flag should only give a warning, and only when set. Therefore, when the
> compiler gives me a warning about someFunction() throw() that uses
> another function without throw(), I can choose to embrace it with
> try/catch(...). Now I now that at least someFunction() won't throw and
> crash on me when the exception reaches the caller that "must never throw".
>
> This way we can make the our own code provide complete no-throw
> guarantees, but not without help from the compiler's warnings.

Yes, that seems possible. Note, however that something innocuous like
std::string s("well now") might throw (bad_alloc is my favorite when
talking exceptions ;-)). Or, many calls to STL might throw. And
standard library does not use exception specification, nor do many
others. So one innocuous library call somewhere and your own spec
becomes invalid (think maintenance). (I guess there are reasons why
standard and other libraries don't use throw() and that this is
related to the spec of throw() and history.)

> > 2. often, a no-throw guarantee is not at the function boundary, but
> > rather just a couple of lines in an existing one. So that makes your
> > idea not-far-reaching-enough (e.g. something like "nothrow {}" would
> > be even more useful. For example, recently someone asked here "what if
> > creation of scope guard throws" and the answer to that is "your job to
> > make sure it does not"; no-one in their right mind would put scope
> > guard creation in a function.
>
> I think that particular someone was me. ;) I try understand all this
> about exception safety, so please excuse my lack of experience.
> Anyway, you write "your job is to make sure it does not" (throw). It is
> my job, yes, but if the compiler could do the job for me, or at least
> warn about a potential meltdown, my job would so much less stressful.
>
> Let's take a good example. Nowhere can I find proper documentation
> whether std::vector's pop_back() throws or not.

True, you don't see it. Practical answer: it's a nothrow operation.
Practical thinking that relates to this, and applies to library
writer: poping is cleanup and cleanup must not throw. I know of no
implementation where that could throw, and would consider it
implementation quality issue if it could. For example, do you know
that pop_back in a vector never changes allocated storage? Downside of
that is that once you reach some high-mark of elements, you don't
never free. But the alternative is worse: if pop-back tried to
reallocate, it would have a failure mode; we don't want that.

> On the contrary, if we
> look at the synopsis for boost::shared_ptr
> (http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm)
> we see that most functions are documented with "// never throws"
> How do we know that? Just because they write it? Or do they actually do
> a try/catch(...) in the code, and if so, why not declare those functions
> with throw()?

Just because they write it. Doing a try/catch would be ludicrous from
performance/code size point, and could also hide a bug in boost,
however unlikely that might be.

BTW, don't you trust e.g. standard lib/booost implementors to do the
right thing? 'cause they do, much more often than I. Their code is
better than mine if nothing else because there's so many eyes on their
code, and so little on mine ;-).

>
> When you write "your job is to make sure it does not" (throw), I claim
> that with the lack of documentation and compiler help, this is not an
> easy task!

That's strange. I claim that it is. Why do you think it is not? In
fact, most of your trouble stems from this uneasy lack-of-safety-
feeling of yours, doesn't it? I honestly don't have that feeling, and
here's why: I find that nothrow pieces are __extremely__ rare in any
code. And that's __EXTREMELY__. Because they are rare, not a lot of
effort goes into making sure they stay nothrow, and one indeed needs
to make a serious error to break that. Finally, due to their very
nature (low level ops, cleanup), I find them easy to spot, too.

> You also write "no-one in their right mind would put scope guard
> creation in a function". I don't think I understand what you meant. I
> would appreciate if you explained that.

I was thinking: would you use scope guard if you had to do this all
the time:

ScopeGuard MakeGuardForX(...) throw() { return MakeGuard(...); }

and then

void f(...)
{
//...
ScopeGuard g = MakeGuardForX();
//...
}

(that is, if you had to have a throw() function for every one of
them?)

I sure wouldn't.

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: DeMarcus on
>
> Yes, that seems possible. Note, however that something innocuous like
> std::string s("well now") might throw (bad_alloc is my favorite when
> talking exceptions ;-)). Or, many calls to STL might throw. And
> standard library does not use exception specification, nor do many
> others. So one innocuous library call somewhere and your own spec
> becomes invalid (think maintenance). (I guess there are reasons why
> standard and other libraries don't use throw() and that this is
> related to the spec of throw() and history.)
>

Maybe I'm slow but I still don't get it. According to the exception
safety rules, a no-throw function like the destructor, pop, etc. must
never throw. Then why on earth can't we put throw() on those functions
since it's a run-time check anyway (and wouldn't break any current code)?

>> Let's take a good example. Nowhere can I find proper documentation
>> whether std::vector's pop_back() throws or not.
>
> True, you don't see it. Practical answer: it's a nothrow operation.
> Practical thinking that relates to this, and applies to library
> writer: poping is cleanup and cleanup must not throw. I know of no
> implementation where that could throw, and would consider it
> implementation quality issue if it could. For example, do you know
> that pop_back in a vector never changes allocated storage? Downside of
> that is that once you reach some high-mark of elements, you don't
> never free. But the alternative is worse: if pop-back tried to
> reallocate, it would have a failure mode; we don't want that.
>

You are right, but now you're talking out of experience. Not everyone
has a vast experience, and it can still be difficult to guess whether a
function is no-throw or not. What would you say about this function for
instance?

someonesFile.close();

It probably should be no-throw, but who knows what the inventor had in
mind writing this File class?


>
> BTW, don't you trust e.g. standard lib/booost implementors to do the
> right thing? 'cause they do, much more often than I. Their code is
> better than mine if nothing else because there's so many eyes on their
> code, and so little on mine ;-).
>

I trust the boost implementors fully, I mean, it was one of the founders
of boost that published the idea of exception safety guarantees; the
technique I'm now working hard to conform to.

Nevertheless, just because they're renowned C++ experts, that doesn't
stop me from proposing enhancements to their ideas.

So if the following holds:

* A no-throw function can, without functional harm, be declared throw()
since such function must throw nothing, compared to a throw( MyException
) that can throw more than just MyException due to templates.

If that holds, then I claim an optional feature in the compiler can, by
means of static checking during compile-time, help finding no-throw
functions that throws anyway. This optional feature would be no
disadvantage, but only an enhancement helping programmers writing
exception safe code.

Please give your comments on this.


Regards,
Daniel



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]