This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: exception specifications
- To: nathan at compsci dot bristol dot ac dot uk
- Subject: Re: exception specifications
- From: "Martin v. Loewis" <martin at mira dot isdn dot cs dot tu-berlin dot de>
- Date: Wed, 3 Mar 1999 18:51:17 +0100
- CC: egcs at egcs dot cygnus dot com
- References: <36DD4CBC.5C0F974@acm.org>
> 15.4/2 says [all decls of a function] "shall have an
> exception-specifier with the same set of type-ids." This implies that
> exception specifiers are sets.
Total agreement here.
> However, 15.4/6 says "an exception specification can include the
> same type more than once, and can include classes that are related
> by inheritance, even though doing so is redundant." So exceptions
> specification are not sets in the mathematical sense, but some kind
> of fuzzy set with semantics we must infer from the standard.
Well, they are sets. Sets can have different external representations,
repeating elements still doesn't change the set, in the mathematil sense:
S = { a, b, c}
S1 = S \/ {a}
S1 == S!
> 1) Are `throw(T)' and `throw(T, T)' the same?
Yes. It looks like this is the reason for allowing duplicates.
> Consider templatized exception> specifiers, ie `template<class T>
> void fn()throw(int, T);' The specialization `template<> void
> fn<int>()throw(int)' would be acceptable, which looks inconsistent.
No. Since we've decided that the throw-spec is not a lexical thing,
but semantical, it is very clear that {int, int} == {int}. Of course,
if people are not aware of this property, they write throw(int,int),
which is just as fine.
> 2) Are `throw(T)' and `throw(T, U)' the same, if U is singly derived
> from T? U is clearly redundant in the latter specification, but does
> that cause it to match the former?
No. U != T, so {T,U} != {U}. Of course, as an optimization, U could be
removed from the list of generated exceptions when generating
assembler code.
> 3) Ditto for T *, U * and for T &, U &.
Ditto.
> 4) (2) and (3) are really asking if 15.4/6 actually means `according
> to the matching semantics of catch clauses'. Then `T cv* cv' and `U
> cv *cv' all come into the picture.
They say mentioning subclasses is redundant, they don't lift the
restriction in 15.4/2, which asks for identical sets. When they say
'redundant', they mean with regard to 15.4/7: The base class already
allows the derived class.
> 5) If you believe we're doing catch clause-like matching, then presumably we
> should be ignoring the toplevel cv qualifiers of type-ids in the exception
> specifier.
We do not. 15.4/7 quite explicitly says what we do.
> 6) If throw(int) and throw(const int) are different throw specifiers,
> then 15.4/3 becomes strange. That says a virtual function overrider
> "shall only allow exceptions that are allowed by the exception
> specification of the base class virtual function". This is looser
> than (2). I.e, an overriding function `void U::fn() throw(int)'
> allows the same exceptions as a base function `void T::fn()
> throw(const int)', even though U::fn's exception specifier is not a
> subset of T::fn's.
No, it doesn't. If the base method allows (int), the derived method
can only *allow* (int) or (), but not (const int).
IMHO, anyway.
Regards,
Martin