    // file      : Example/ExH/Compound/compound.cpp
    // author    : Boris Kolpackov <boris@kolpackov.net>
    // copyright : Copyright (c) 2002-2003 Boris Kolpackov
    // license   : http://kolpackov.net/license.html

    #include "Utility/ExH/Compound.hpp"
    #include "Utility/ExH/System/Exception.hpp"
    #include "Utility/ExH/Logic/DescriptiveException.hpp"

    // Include some helper converters to allow exception initialization
    // with std::ostringstream

    #include "Utility/ExH/StringStreamConverter.hpp"

    #include <iostream>

    using std::cerr;
    using std::endl;
    using std::string;
    using std::ostringstream;

    using namespace Utility::ExH;

    // Here are our components

    class Base
    {
    public:

      //
      // Exception definitions.
      //

      // Base logic exception class for component.
      class Exception_ {};
      typedef
      Compound <Exception_, Logic::DescriptiveException>
      Exception;

      class InvalidArgument_ {};
      typedef
      Compound <InvalidArgument_, Exception>
      InvalidArgument;

      class NotInitialized_ {};
      typedef
      Compound <NotInitialized_, Exception>
      NotInitialized;

    public:

      void
      foo (char const* str) throw (InvalidArgument, NotInitialized)
      {
        // This is just an example.

        if (str == 0)
        {
          throw InvalidArgument ("Base::foo: first parameter is zero.");
        }
        else
        {
          ostringstream ostr;
          ostr << "Base::foo [this = " << this << "]: object is not initialized.";

          throw NotInitialized (ostr);
        }
      }

      // We don't know what implementation may decide to throw so
      // we allow to throw System exception and any logic exception
      // derived from Base::Exception
      virtual void
      vfoo () throw (Exception, System::Exception) = 0;
    };

    class Derived : public Base
    {
    public:

      // Define some Derived-specific logic exception.
      class NotImplemented_ {};
      typedef
      Compound <NotImplemented_, Exception>
      NotImplemented;

    public:
      virtual void
      vfoo () throw (NotImplemented, System::Exception)
      {
        std::string str ("Derived::vfoo: not implemented yet.");
        throw NotImplemented (str);
      }
    };

    int
    main ()
    {
      try
      {

        Derived d;
        Base* pb (&d);

        // We can use generic handler.
        try
        {
          pb->vfoo ();
        }
        catch (Base::Exception const& ex)
        {
          cerr << "Caught Base::Exception: " << ex.what () << endl;
        }

        // Or use more precise control.
        try
        {
          pb->foo ("hello");
        }
        catch (Base::NotInitialized const& ex)
        {
          cerr << "Caught Base::NotInitialized: " << ex.what () << endl;
        }

        // Or use application-level handler.
        pb->foo (0);

      }
      catch (Logic::Exception const& ex)
      {
        cerr << "Caught Logic::Exception: " << ex.what () << endl;
      }
      catch (...)
      {
        cerr << "Caught unknown exception using catch-all handler" << endl;
        return -1;
      }

    }