This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.

### 2015. Incorrect pre-conditions for some type traits

Section: 20.15.5 [meta.unary] Status: C++14 Submitter: Nikolay Ivchenkov Opened: 2010-11-08 Last modified: 2016-01-28

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 20.15.5.4 [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 20.15.7 [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 ]
   > ...