Topic: Exceptions specifications for function templates


Author: fjh@cs.mu.oz.au (Fergus Henderson)
Date: 1995/08/16
Raw View
mueller@garwein.hai.siemens.co.at (Harald M. Mueller) writes:

>I did no find an answer/hint/idea for this in the C++ standard:
>What should the exception specification be for
>
>                template <class T>
>                void swap(T& a, T& b)   throw(???)
>                { T tmp = a; a = b; b = tmp;
>                }
>
>- we do not know the exceptions that might be thrown by
>the copy constructor or assignment operator of T!
>As far as I can see, there are three ways out of this problem:
>
>    (a) Require that all called functions adhere to the
>        exception specification supplied [...]
>        This, of course, makes it impossible to use the
>        template for types supplied by third parties who do
>        not know about this restriction.

Yes, that is pretty undesireable.

>    (b) Catch unspecified exceptions possibly thrown inside the
>        calling function and throw an exception allowed by
>        the supplied exception specification:
>
>        class Xswap {};         // exception meaning "something
>                                // went wrong in swap"
>        template <class T>
>        void swap(T& a, T& b)   throw(Xswap)
>        { try {
>              T tmp = a; a = b; b = tmp;
>          } catch(...) {
>              throw Xswap();
>          }
>        }
>
>        This, in effect, destroys all the information which
>        might be contained in a thrown exception, and
>        therefore reduces the information transported by an
>        exception to the single bit "something went wrong".

You could improve on this a little, albeit at some cost in
complexity:

// base class for exception hierarchy
struct Exception {
// return a dynamically allocated copy of myself
virtual Exception* clone() = 0;
}

// exception meaning "something went wrong in swap"
struct Xswap : Exception {
Exception *cause; // records what went wrong
Xswap(Exception *c = NULL) : cause(c) {}
Exception *clone() { return new Xswap(*this); }
};

template <class T>
void swap(T& a, T& b)   throw(Xswap)
{ try {
T tmp = a; a = b; b = tmp;
}
catch(Exception& e) {
throw Xswap(e.clone());
}
catch(...) {
throw Xswap();
}
}

This gets very tricky very quickly if you try to handle memory allocation and
deallocation correctly (the above code basically assumes garbage collection),
especially if you want to be able to handle out-of-memory conditions.

>    (c) Do not use exception specifications if unknown exceptions
>        might be thrown:
>
>        template <class T>
>        void swap(T& a, T& b)
>        { T tmp = a; a = b; b = tmp;
>        }
>
>        The disadvantage of this is, of course, that no
>        automatic run-time check of the thrown exceptions is
>        possible.

Why is that a disadvantage?

>Although I do it only reluctantly, I opt for version (c) because
>the restrictions brought about by (a) and (b) are too heavy, in
>my opinion - or did I overlook something???
>
>Big Q: How do the standardization people intend to write the
>exceptions specifications for all the function templates in
>the standard?

I think not - I think they're going for (c) too.

--
Fergus Henderson              | Designing grand concepts is fun;
fjh@cs.mu.oz.au               | finding nitty little bugs is just work.
http://www.cs.mu.oz.au/~fjh   | -- Brooks, in "The Mythical Man-Month".
PGP key fingerprint: 00 D7 A2 27 65 09 B6 AC  8B 3E 0F 01 E7 5D C4 3F
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: mueller@garwein.hai.siemens.co.at (Harald M. Mueller)
Date: 1995/08/07
Raw View
I did no find an answer/hint/idea for this in the C++ standard:
What should the exception specification be for

                template <class T>
                void swap(T& a, T& b)   throw(???)
                { T tmp = a; a = b; b = tmp;
                }

- we do not know the exceptions that might be thrown by
the copy constructor or assignment operator of T!
As far as I can see, there are three ways out of this problem:

    (a) Require that all called functions adhere to the
        exception specification supplied, e.g.,

        template <class T>
        void swap(T& a, T& b)   throw(bad_alloc)
        { T tmp = a; a = b; b = tmp;
        }

        Here swap must only be instantiated with types
        where the copy constructor as well as the assignment
        operator promise to throw nothing but bad_alloc
        exceptions.

        This, of course, makes it impossible to use the
        template for types supplied by third parties who do
        not know about this restriction.

    (b) Catch unspecified exceptions possibly thrown inside the
        calling function and throw an exception allowed by
        the supplied exception specification:

        class Xswap {};         // exception meaning "something
                                // went wrong in swap"
        template <class T>
        void swap(T& a, T& b)   throw(Xswap)
        { try {
              T tmp = a; a = b; b = tmp;
          } catch(...) {
              throw Xswap();
          }
        }

        This, in effect, destroys all the information which
        might be contained in a thrown exception, and
        therefore reduces the information transported by an
        exception to the single bit "something went wrong".

    (c) Do not use exception specifications if unknown exceptions
        might be thrown:

        template <class T>
        void swap(T& a, T& b)
        { T tmp = a; a = b; b = tmp;
        }

        The disadvantage of this is, of course, that no
        automatic run-time check of the thrown exceptions is
        possible.

Although I do it only reluctantly, I opt for version (c) because
the restrictions brought about by (a) and (b) are too heavy, in
my opinion - or did I overlook something???

Big Q: How do the standardization people intend to write the
exceptions specifications for all the function templates in
the standard?

HMMueller

== --------------------------------------------------------------
== Dr. Harald M. Mueller mueller@garwein.hai.siemens.co.at
== Siemens AG Austria  Siemens AG Austria
== PSE EZE TNA1   Erdberger Laende 26
== fax: +43-1-71711-5425 A-1030 Vienna/Austria
== --------------------------------------------------------------