Title
is_destructible is underspecified
Status
c++14
Section
[meta.unary.prop]
Submitter
Daniel Krügler

Created on 2011-04-18.00:00:00 last changed 123 months ago

Messages

Date: 2012-11-03.04:16:46

Proposed resolution:

Update [meta.unary.prop], table 49:

template <class T> struct is_destructible; For a complete type T and given template <class U> struct test { U u; };, test<T>::~test() is not deleted.
For reference types, is_destructible<T>::value is true.
For incomplete types and function types, is_destructible<T>::value is false.
For object types and given U equal to remove_all_extents<T>::type,
if the expression std::declval<U&>().~U() is well-formed when treated as an
unevaluated operand (Clause [expr]), then is_destructible<T>::value is true,
otherwise it is false.
T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
Date: 2012-11-03.04:16:46

[ 2012, Portland: applied to WP ]

Date: 2012-02-12.18:36:43

[ 2012, Kona ]

Moved to Tentatively Ready by the post-Kona issues processing subgroup.

Date: 2011-08-20.00:00:00

[ 2011-08-20 Daniel comments and provides alternatives wording ]

The currently proposed wording would have the consequence that every array type is not destructible, because the pseudo-destructor requires a scalar type with the effect that the expression

std::declval<T&>().~T()

is not well-formed for e.g. T equal to int[3]. The intuitive solution to fix this problem would be to adapt the object type case to refer to the expression

std::declval<U&>().~U()

with U equal to remove_all_extents<T>::type, but that would have the effect that arrays of unknown bounds would be destructible, if the element type is destructible, which was not the case before (This was intentionally covered by the special "For a complete type T" rule in the FDIS).

Suggestion: Use the following definition instead:

Let U be remove_all_extents<T>::type.
For incomplete types and function types, is_destructible<T>::value is false.
For object types, if the expression std::declval<U&>().~U() is well-formed
when treated as an unevaluated operand (Clause 5), then is_destructible<T>::value
is true, otherwise it is false.
For reference types, is_destructible<T>::value is true.

This wording also harmonizes with the "unevaluated operand" phrase used in other places, there does not exist the definition of an "unevaluated context"

Note: In the actually proposed wording this wording has been slightly reordered with the same effects.

Howard's (old) proposed resolution:

Update [meta.unary.prop], table 49:

template <class T> struct is_destructible; For a complete type T and given template <class U> struct test { U u; };, test<T>::~test() is not deleted.
For object types, if the expression: std::declval<T&>().~T() is well-formed in an unevaluated context then is_destructible<T>::value is true, otherwise it is false.
For void types, is_destructible<T>::value is false.
For reference types, is_destructible<T>::value is true.
For function types, is_destructible<T>::value is false.
T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.

Date: 2011-08-17.12:17:15

[ 2011 Bloomington ]

After discussion about to to handle the exceptional cases of reference types, function types (available by defererencing a function pointer) and void types, Howard supplied proposed wording.

Date: 2011-04-23.20:00:34

The conditions for the type trait is_destructible to be true are described in Table 49 — Type property predicates:

For a complete type T and given
template <class U> struct test { U u; };,
test<T>::~test() is not deleted.

This specification does not say what the result would be for function types or for abstract types:

  1. For an abstract type X the instantiation test<X> is already ill-formed, so we cannot say anything about whether the destructor would be deleted or not.
  2. In regard to function types, there exists a special rule in the core language, [temp.arg.type] p. 3, which excludes member functions to be declared via the type of the template parameter:

    If a declaration acquires a function type through a type dependent on a template-parameter and this causes a declaration that does not use the syntactic form of a function declarator to have function type, the program is ill-formed.

    [ Example:

    template<class T> struct A {
      static T t;
    };
    typedef int function();
    A<function> a; // ill-formed: would declare A<function>::t
                   // as a static member function
    

    end example ]

    which has the same consequence as for abstract types, namely that the corresponding instantiation of test is already ill-formed and we cannot say anything about the destructor.

To solve this problem, I suggest to specify function types as trivially and nothrowing destructible, because above mentioned rule is very special for templates. For non-templates, a typedef can be used to introduce a member as member function as clarified in [dcl.fct] p. 10.

For abstract types, two different suggestions have been brought to my attention: Either declare them as unconditionally non-destructible or check whether the expression

std::declval<T&>().~T()

is well-formed in an unevaluated context. The first solution is very easy to specify, but the second version has the advantage for providing more information to user-code. This information could be quite useful, if generic code is supposed to invoke the destructor of a reference to a base class indirectly via a delete expression, as suggested by Howard Hinnant:

template <class T>
my_pointer<T>::~my_pointer() noexcept(is_nothrow_destructible<T>::value)
{
   delete ptr_;
}

Additional to the is_destructible traits, its derived forms is_trivially_destructible and is_nothrow_destructible are similarly affected, because their wording refers to "the indicated destructor" and probably need to be adapted as well.

History
Date User Action Args
2014-02-20 13:20:35adminsetstatus: wp -> c++14
2012-11-03 04:16:46adminsetmessages: + msg6261
2012-10-25 12:46:45adminsetstatus: voting -> wp
2012-10-16 15:35:12adminsetstatus: ready -> voting
2012-02-12 18:36:43adminsetmessages: + msg5997
2012-02-12 18:36:43adminsetstatus: review -> ready
2011-11-21 23:18:51adminsetmessages: + msg5881
2011-08-17 12:17:15adminsetmessages: + msg5860
2011-08-17 12:17:15adminsetmessages: + msg5859
2011-08-17 12:17:15adminsetstatus: open -> review
2011-08-16 10:45:53adminsetstatus: new -> open
2011-04-18 00:00:00admincreate