Topic: const_cast and throw( ) clauses


Author: smeyers@teleport.com (Scott Meyers)
Date: 1996/10/13
Raw View
In article <32594DB9.1648@elastic.avid.com>,
Garth A. Dickie <dickie@fantasia.avid.com> wrote:
| Apparently a throw( ) clause is part of a function's type, so that we
| can write:
|
|     typedef void ( * ProgressMeterCallback )( double amountDone ) throw( );

Ah, last I checked, we can't, but thank you for the opportunity to bring
this up once again.  I posted the following on April 30 and got no
response, so I posted it again on July 22, and again I got no response.
This makes my third posting, and would somebody who knows something PLEASE
say something about this?  This is important, and not just because the
accuracy of one passage in my book is at stake.

Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
| Jack Reeves wrote:
| > Can anyone explain why the DWP explicity disallows exception
| > specifications on a typedef?
|
| Because it's not part of the type. And a good thing too, since exception
| specs are far more likely to change in a library routine than the actual
| arg and return types.

Exception specs may not technically be part of a function's type, but note
that they are checked in many cases.  From DWP 15.4:

  2 If  any  declaration of a function has an exception-specification, all
    declarations, including the definition, of that function shall have an
    exception-specification  with  the same set of type-ids.  If a virtual
    function has an exception-specification, all  declarations,  including
    the  definition,  of any function that overrides that virtual function
    in any derived class shall have an exception-specification at least as
    restrictive as that in the base class.  [Example:
            struct B {
                virtual void f() throw (int, double);
                virtual void g();
            };

            struct D: B {
                void f();                    // ill-formed
                void g() throw (int);        // OK
            };
      --end  example]  The  declaration  of  D::f is ill-formed because it
    allows all exceptions, whereas B::f allows only int and double.  Simi-
    larly,  any function or pointer to function assigned to, or initializ-
    ing, a pointer to function shall have  an  exception-specification  at
    least as restrictive as that of the pointer or function being assigned
    to or initialized.  [Example:
            void (*pf1)();    // no exception specification
            void (*pf2) throw(A);

            void f()
            {
                    pf1 = pf2;  // ok: pf1 is less restrictive
                    pf2 = pf1;  // error: pf2 is more restrictive
            }
     --end example]

  3 In such an assignment or initialization,  exception-specifications  on
    return types and parameter types shall match exactly.

  4 In  other  assignments  or  initializations,  exception-specifications
    shall match exactly.

Given that the syntax of function pointers is one of the best arguments for
typedefs and given that exception specs are checked during initialization
and assignment of function pointers, the explicit restriction against the
use of exception specs in typedefs seems almost cruel.  Unless there is a
better argument against allowing exception specs in typedefs, I think the
prohibition should be reconsidered.

Scott

--
Scott Meyers, Ph.D.                  Voice: 503/638-6028
C++ Consulting and Training          Fax:   503/638-6614
Author of "Effective C++"            Email: smeyers@netcom.com
  and "More Effective C++"           WWW:   http://www.teleport.com/~smeyers


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Garth A. Dickie" <dickie@fantasia.avid.com>
Date: 1996/10/07
Raw View
Apparently a throw( ) clause is part of a function's type, so that we
can write:

    typedef void ( * ProgressMeterCallback )( double amountDone ) throw( );

Then the following will be a compile-time error:

    void Compute( ..., ProgressMeterCallback progressMeterCallback ) { }
    void OopsCallback( double amountDone ) { }

    Compute( ..., OopsCallback ) // error -- OopsCallback needs throw( ) clause.

I would like to know what cast can be used to remove or change
the throw( ) clause part of a function pointer.  The natural place
for this seems to be const_cast.  If it is not already possible, I
would like to propose that it be made possible.

If you know in a given context that OopsCallback will not throw
any exception, you can then write

    Compute( ..., const_cast< ProgressMeterCallback >( OopsCallback )) // no error

Just as with const_cast used to cast away const or volatile, the
types must match except in their const, volatile, or throw( ) qualifiers.
In addition, a static_cast will not allow the removal or weakening of a
throw( ) qualifier.

Comments?  Is this already in there and I didn't know it?  Are there any
problems with this approach?

Regards,
Garth A. Dickie


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]