2015. Incorrect pre-conditions for some type traits

Section: 23.15.4 [meta.unary] Status: C++14 Submitter: Nikolay Ivchenkov Opened: 2010-11-08 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [meta.unary].

View all issues with C++14 status.

Discussion:

According to N3126 ‑ 3.9/9,

"Scalar types, trivial class types (Clause 9), arrays of such types and cv‑qualified versions of these types (3.9.3) are collectively called trivial types."

Thus, an array (possibly of unknown bound) can be trivial type, non‑trivial type, or an array type whose triviality cannot be determined because its element type is incomplete.

According to N3126 ‑ Table 45, preconditions for std::is_trivial are defined as follows:

"T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound"

It seems that "an array of unknown bound" should be changed to "an array of unknown bound of a complete element type". Preconditions for some other templates (e.g., std::is_trivially_copyable, std::is_standard_layout, std::is_pod, and std::is_literal_type) should be changed similarly.

On the other hand, some preconditions look too restrictive. For example, std::is_empty and std::is_polymorphic might accept any incomplete non‑class type.

[2011-02-18: Daniel provides wording proposal]

While reviewing the individual preconditions I could find three different groups of either too weakening or too strengthening constraints:

  1. is_empty/is_polymorphic/is_abstract/has_virtual_destructor:

    These traits can only apply for non‑union class types, otherwise the result must always be false

  2. is_base_of:

    Similar to the previous bullet, but the current wording comes already near to that ideal, it only misses to add the non‑union aspect.

  3. is_trivial/is_trivially_copyable/is_standard_layout/is_pod/is_literal_type:

    These traits always require that std::remove_all_extents<T>::type to be cv void or a complete type.

[Bloomington, 2011]

Move to Ready

Proposed resolution:

  1. Modify the pre-conditions of the following type traits in 23.15.4.3 [meta.unary.prop], Table 48 — Type property predicates:

    Table 48 — Type property predicates
    Template Condition Preconditions
    ...
    template <class T>
    struct is_trivial;
    T is a trivial type (3.9) remove_all_extents<T>::type
    shall be a complete type, or (possibly
    cv-qualified) void, or an array of
    unknown bound
    .
    template <class T>
    struct is_trivially_copyable;
    T is a trivially copyable
    type (3.9)
    remove_all_extents<T>::type
    shall be a complete type, or (possibly
    cv-qualified) void, or an array of
    unknown bound
    .
    template <class T>
    struct is_standard_layout;
    T is a standard-layout
    type (3.9)
    remove_all_extents<T>::type
    shall be a complete type, or (possibly
    cv-qualified) void, or an array of
    unknown bound
    .
    template <class T>
    struct is_pod;
    T is a POD type (3.9) remove_all_extents<T>::type
    shall be a complete type, or (possibly
    cv-qualified) void, or an array of
    unknown bound
    .
    template <class T>
    struct is_literal_type;
    T is a literal type (3.9) remove_all_extents<T>::type
    shall be a complete type, or (possibly
    cv-qualified) void, or an array of
    unknown bound
    .
    template <class T>
    struct is_empty;
    T is a class type, but not a
    union type, with no
    non-static data members
    other than bit-fields of
    length 0, no virtual
    member functions, no
    virtual base classes, and
    no base class B for which
    is_empty<B>::value is
    false.
    T shall be a complete type,
    (possibly cv-qualified) void, or
    an array of unknown bound
    If T
    is a non‑union class type, T
    shall be a complete type
    .
    template <class T>
    struct is_polymorphic;
    T is a polymorphic
    class (10.3)
    T shall be a complete type,
    type, (possibly cv-qualified) void, or
    an array of unknown bound
    If T
    is a non‑union class type, T
    shall be a complete type
    .
    template <class T>
    struct is_abstract;
    T is an abstract
    class (10.4)
    T shall be a complete type,
    type, (possibly cv-qualified) void, or
    an array of unknown bound
    If T
    is a non‑union class type, T
    shall be a complete type
    .
    ...
    template <class T>
    struct has_virtual_destructor;
    T has a virtual
    destructor (12.4)
    T shall be a complete type,
    (possibly cv-qualified) void, or
    an array of unknown bound
    If T
    is a non‑union class type, T
    shall be a complete type
    .
  2. Modify the pre-conditions of the following type traits in 23.15.6 [meta.rel], Table 50 — Type relationship predicates:

    Table 50 — Type relationship predicates
    Template Condition Comments
    ...
    template <class Base, class
    Derived>
    struct is_base_of;
    Base is a base class of
    Derived (10) without
    regard to cv-qualifiers
    or Base and Derived
    are not unions and
    name the same class
    type without regard to
    cv-qualifiers
    If Base and Derived are
    non‑union class types
    and are different types
    (ignoring possible cv-qualifiers)
    then Derived shall be a complete
    type. [ Note: Base classes that
    are private, protected, or
    ambigious are, nonetheless, base
    classes. — end note ]
    ...