← Back to team overview

dolfin team mailing list archive

Re: GenericTensor::down_cast() should throw std::bad_cast instead of invoking dolfin::error

 

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

To round up the discussion: I wasn't aware of GenericTensor::has_type().
I think that is the more "correct" way of doing what I want, i.e.
instead of casting and catching the exception or doing a tentative
dynamic_cast and checking for a null pointer one should check through
has_type() if the down_cast is safe.

As an aside, using dynamic_cast always return a null pointer in my case
even though the down_cast would succeed. I couldn't really figure out
what was the reason for that, but above method using has_type() works fine.

Florian

On 04.08.2010 12:47, Florian Rathgeber wrote:
> On 04.08.2010 11:22, Garth N. Wells wrote:
>> On Wed, 2010-08-04 at 11:18 +0200, Florian Rathgeber wrote:
>> On 03.08.2010 21:21, Anders Logg wrote:
>>>>> On Tue, Aug 03, 2010 at 06:19:16PM +0100, Garth N. Wells wrote:
>>>>>> On Tue, 2010-08-03 at 19:14 +0200, Anders Logg wrote:
>>>>>>> On Tue, Aug 03, 2010 at 03:41:35PM +0100, Garth N. Wells wrote:
>>>>>>>> On Tue, 2010-08-03 at 07:51 +0200, Florian Rathgeber wrote:
>>>>>>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>>>>>>> Hash: SHA1
>>>>>>>>>
>>>>>>>>> On 02.08.2010 18:50, Garth N. Wells wrote:
>>>>>>>>>> On Mon, 2010-08-02 at 10:33 +0200, Anders Logg wrote:
>>>>>>>>>>> On Sun, Aug 01, 2010 at 06:35:22PM +0100, Garth N. Wells wrote:
>>>>>>>>>>>> On Sun, 2010-08-01 at 12:40 +0200, Florian Rathgeber wrote:
>>>>>>>>>>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>>>>>>>>>>> Hash: SHA1
>>>>>>>>>>>>>
>>>>>>>>>>>>> Hi,
>>>>>>>>>>>>>
>>>>>>>>>>>>> When using GenericTensor::down_cast() for a tentative down cast it would
>>>>>>>>>>>>> be helpful if it would throw std::bad_alloc (as any dynamic_cast would
>>>>>>>>>>>>> do)
>>>>>>>>>>>>
>>>>>>>>>>>> Do you mean std::bad_cast?
>>>>>>>>>>>>
>>>>>>>>>>>>> instead of invoking dolfin::error. Currently you would have to catch
>>>>>>>>>>>>> std::runtime_error and check what() to distinguish a failed cast from
>>>>>>>>>>>>> another dolfin::error, which is pretty inconvenient. Is there a specific
>>>>>>>>>>>>> reason why it is implemented this way?
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Not really.
>>>>>>>>>>>>
>>>>>>>>>>>> It's not too clear to me what you'd like. Would you prefer that
>>>>>>>>>>>> down_cast doesn't throw an error, but leave it up to the programmer to
>>>>>>>>>>>> check that a cast was successful, or just that DOLFIN catch a
>>>>>>>>>>>> std::bad_cast and print more information before throwing an error?
>>>>>>>>>>>
>>>>>>>>>>> I think the best would be if DOLFIN caught the error, then wrote an
>>>>>>>>>>> informative message (since it knows exactly what went wrong) and then
>>>>>>>>>>> threw bad_cast.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Looks like there isn't much that can be done - std::bad_cast is only
>>>>>>>>>> thrown when casting references, not pointers (as we do internally). From
>>>>>>>>>> what I've read, our way of checking for a null pointer is correct.
>>>>>>>>>
>>>>>>>>> If down_cast() were implemented as casting the reference directly,
>>>>>>>>> dynamic_cast would throw std::bad_cast if it fails.
>>>>>>>>>
>>>>>>>>> The check for the null pointer is correct, my point is that in this case
>>>>>>>>> not a std::runtime_error should be thrown (which happens by calling
>>>>>>>>> dolfin::error), but instead the message should be printed e.g. by
>>>>>>>>> dolfin::warning and then a std::bad_cast thrown. That was Anders'
>>>>>>>>> suggestion if I got that right.
>>>>>>>>>
>>>>>>>>> In that way down_cast() could be used as a tentative cast which is not
>>>>>>>>> really possible if it throws the same exception that could be caused by
>>>>>>>>> and DOLFIN error.
>>>>>>>>>
>>>>>>>>
>>>>>>>> GenericTensor::down_cast now catches an exception and then throws an
>>>>>>>> error. It was simpler than I thought because return statements can be
>>>>>>>> used inside a try block (which I didn't know).
>>>>>>>>
>>>>>>>> Garth
>>>>>>>
>>>>>>> Does this work as intended? It still looks like we catch the exception
>>>>>>> and let then throw a runtime error by calling error():
>>>>>>>
>>>>>>>  catch (std::exception& e)
>>>>>>>  {
>>>>>>>    error("GenericTensor cannot be cast to the requested type: %s", e.what());
>>>>>>>  }
>>>>>>>
>>>>>>
>>>>>> Yes. What else do we want to do other than eventually throw an error? We
>>>>>> don't want to carry on with a bad cast. If a programmer wants to do
>>>>>> something fancy when a cast fails, they can use dynamic_cast directly
>>>>>> and catch an exception.
>>>>>>
>>>>>> Garth
>>>>>
>>>>> I thought the idea was to throw a more specific exception since we
>>>>> know exactly what type of exception it is. We throw away that
>>>>> information when we just call error. Maybe the error() function should
>>>>> take the exception as an argument so that it can throw that exception
>>>>> instead of just runtime_error?
>>>>>
>>>>> --
>>>>> Anders
> 
>> I agree with Anders. Calling error doesn't give the user the possibility
>> to _only_ catch a dynamic_cast exception through catching std::bad_cast.
>> She would still have to catch std::runtime_error and figure out what
>> actually happened.
> 
> 
>>> If that's desired, then just use dynamic_cast and catch the exception.
>>> It's simpler than having a GenericTensor member function do it.
>>> GenericTensor::down_cast is a convenience function and the priority is
>>> that it is safe.
> 
>>> Garth
> 
> I used GenericTensor::down_cast since it was convenient. But I
> understand that it's desirable to only have one kind of exception in
> terms of general library design. I can live with using a dynamic_cast
> for that purpose, just wanted to bring up the issue and hear your
> opinions on it
> 
> Florian
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.12 (MingW32)

iEYEARECAAYFAkxcGT0ACgkQ8Z6llsctAxYd7wCaA/2c4101U5sH8z6alwiQ3gcJ
XnIAn1pV45ulIqHzCyq76B3+gKldEEsT
=Xe18
-----END PGP SIGNATURE-----

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


References