Title
Resolution to LWG 2484 is missing "otherwise, no effects" and is hard to parse
Status
c++17
Section
[except.nested]
Submitter
Jonathan Wakely

Created on 2016-10-15.00:00:00 last changed 81 months ago

Messages

Date: 2016-11-21.05:09:01

Proposed resolution:

This wording is relative to N4606.

  1. Modify [except.nested] p9:

    template <class E> void rethrow_if_nested(const E& e);
    

    -9- Effects: If E is not a polymorphic class type, or if nested_exception is an inaccessible or ambiguous base class of E, there is no effect. Otherwise, if the static type or the dynamic type of e is nested_exception or is publicly and unambiguously derived from nested_exception, callsperforms:

    dynamic_cast<const nested_exception&>(e).rethrow_nested();
    if (auto p = dynamic_cast<const nested_exception*>(addressof(e)))
      p->rethrow_nested();
    
Date: 2016-11-15.00:00:00

[ 2016-11-12, Issaquah ]

Sat AM: Priority 0; move to Ready

Date: 2016-10-15.00:00:00

The discussion notes for LWG 2484 point out there should be an "else, no effects" at the end, which didn't make it into the resolution. Without this it's unclear whether it should do nothing, or be ill-formed, or undefined.

Additionally, the precise effects of the Effects are hard to determine, because the conditions on the static type and dynamic type are intermingled, but must actually be checked separately (the static checks must be done statically and the dynamic checks must be done dynamically!) Furthermore, the obvious way to know if "the dynamic type of e is nested_exception or is publicly and unambiguously derived from nested_exception" is to use dynamic_cast, so we have to use dynamic_cast to find out whether to perform the dynamic_cast expression specified in the Effects. It would make more sense to specify it in terms of a dynamic_cast to a pointer type, and only call rethrow_nested() if the result is not null.

The entire spec can be expressed in C++17 as:

if constexpr(is_polymorphic_v<E> && (!is_base_of_v<nested_exception, E> || is_convertible_v<E*, nested_exception*>))
  if (auto p = dynamic_cast<const nested_exception*>(addressof(e)))
    p->rethrow_nested();

This uses traits to perform checks on the static type, then uses dynamic_cast to perform the checks on the dynamic type. I think the spec would be clearer if it had the same structure.

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2017-03-05 23:41:16adminsetstatus: ready -> wp
2016-11-21 05:09:01adminsetmessages: + msg8667
2016-11-21 05:09:01adminsetstatus: new -> ready
2016-10-15 13:23:10adminsetmessages: + msg8567
2016-10-15 00:00:00admincreate