Document number: | N2984=09-0174 |
Date: | 2009-10-23 |
Project: | Programming Language C++, Library Working Group |
Reply-to: | Beman Dawes <bdawes at acm dot org> Daniel Krügler <daniel.kruegler at googlemail dot Alisdair Meredith <public at alisdairm dot net> |
The C++ committee's Library Working Group (LWG) asked in Frankfurt for a proposal unifying LWG requests for additional type traits in light of the removal of the concepts language feature from C++0x.
N2984 - Revision 1
N2947 - Initial version.
LWG issue 1174, submitted by Jason Merrill:
I've been implementing compiler support for is_standard_layout, and noticed a few nits about 20.6.4.3 [meta.unary.prop]:
- There's no trait for "trivially copyable type", which is now the property that lets you do bitwise copying of a type, and therefore seems useful to be able to query. has_trivial_assign && has_trivial_copy_constructor && has_trivial_destructor is similar, but not identical, specifically with respect to const types.
- has_trivial_copy_constructor and has_trivial_assign lack the "or an array of such a class type" language that most other traits in that section, including has_nothrow_copy_constructor and has_nothrow_assign, have; this seems like an oversight.
[ See the thread starting with c++std-lib-24420 for further discussion. ]
is_trivially_copyable
is believed to require compiler support.
LWG issue 719, submitted by Daniel Krügler:
Since the inclusion of constexpr in the standard draft N2369 we have a new type category "literal", which is defined in 3.9 [basic.types]/p.11:
-11- A type is a literal type if it is:
- a scalar type; or
- a class type (clause 9) with
- a trivial copy constructor,
- a trivial destructor,
- a trivial default constructor or at least one constexpr constructor other than the copy constructor,
and- all non-static data members and base classes of literal types; or
- an array of literal type.
I strongly suggest that the standard provides a type traits for literal types in 20.6.4.3 [meta.unary.prop] for several reasons:
- To keep the type traits in sync with the types defined in the core language.
- I see many reasons for programmers to use this trait in template code to provide optimized template definitions for these types, see below.
- A user-provided definition of this trait is practically impossible to write portably.
The special problem of reason (c) is that I don't see currently a way to portably test the condition for literal class types:
- ...at least one constexpr constructor other than the copy constructor,
is_literal_type
is believed to require compiler support.
The proposed name is is_literal_type
, rather than
is_literal
, because literal and literal type have different
core language meanings. It was judged better to be clear even at the cost of
being inconsistent with the other names.
This is a critical trait that came out of exception-safety considerations discussed in N2953, Defining Move Special Member Functions, given the possible presence of throwing and non-throwing copy/move operations.
From N2953:
"However, throwing moves are problematic within the library, and some library specifications prohibit throwing moves. To enable conditional definition of move operations within the library, we add an
is_nothrow_constructible
variadic type trait."
is_nothrow_constructible
is believed to require compiler
support.
is_constructible
is the foundation upon which
is_nothrow_constructible
and is_explictly_convertible are built.
is_constructible
is believed to require compiler support.
Omitting is_constructible
in the presence of
is_nothrow_constructible
would be inconsistent with other traits that
have an is_nothrow_*
counterpart.
The cost of specifying this additional trait is outweighed by the consistency
concern, and to satisfy user-expectations. Additionally, the trickiest part of
the specification of is_nothrow_constructible
is the
is_constructible
subpart. So this work has to be done anyhow.
LWG issue 750, submitted by Alisdair Meredith:
The current definition for is_convertible requires that the type be implicitly convertible, so explicit constructors are ignored.
With the pending arrival of explicit conversion functions though, I'm wondering if we want an additional trait, is_explictly_convertible?
Several LWG members have commented that they believe such a trait would be useful.
is_explicitly_convertible
is believed to require compiler
support unless is_constructible
is available.
LWG issue 1055, addressing CD-1comment UK 98:
It would be useful to be able to determine the underlying type of an arbitrary enumeration type. This would allow safe casting to an integral type (especially needed for scoped enums, which do not promote), and would allow use of numeric_limits. In general it makes generic programming with enumerations easier.
underlying_type
is believed to require compiler support.
To 20.6.2 Header <type_traits> synopsis [meta.type.synop], add as indicated:
namespace std { // 20.6.3, helper class: template <class T, T v> struct integral_constant; typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type; // 20.6.4.1, primary type categories: template <class T> struct is_void; template <class T> struct is_integral; template <class T> struct is_floating_point; template <class T> struct is_array; template <class T> struct is_pointer; template <class T> struct is_lvalue_reference; template <class T> struct is_rvalue_reference; template <class T> struct is_member_object_pointer; template <class T> struct is_member_function_pointer; template <class T> struct is_enum; template <class T> struct is_union; template <class T> struct is_class; template <class T> struct is_function; // 20.6.4.2, composite type categories: template <class T> struct is_reference; template <class T> struct is_arithmetic; template <class T> struct is_fundamental; template <class T> struct is_object; template <class T> struct is_scalar; template <class T> struct is_compound; template <class T> struct is_member_pointer; // 20.6.4.3, type properties: template <class T> struct is_const; template <class T> struct is_volatile; template <class T> struct is_trivial; template <class T> struct is_trivially_copyable; template <class T> struct is_standard_layout; template <class T> struct is_pod; template <class T> struct is_literal_type; template <class T> struct is_empty; template <class T> struct is_polymorphic; template <class T> struct is_abstract; template <class T, class... Args> struct is_constructible; template <class T, class... Args> struct is_nothrow_constructible; template <class T> struct has_trivial_default_constructor; template <class T> struct has_trivial_copy_constructor; template <class T> struct has_trivial_assign; template <class T> struct has_trivial_destructor; template <class T> struct has_nothrow_default_constructor; template <class T> struct has_nothrow_copy_constructor; template <class T> struct has_nothrow_assign; template <class T> struct has_virtual_destructor; template <class T> struct is_signed; template <class T> struct is_unsigned; template <class T> struct alignment_of; template <class T> struct rank; template <class T, unsigned I = 0> struct extent; // 20.6.5, type relations: template <class T, class U> struct is_same; template <class Base, class Derived> struct is_base_of; template <class From, class To> struct is_convertible; template <class From, class To> struct is_explicitly_convertible; // 20.6.6.1, const-volatile modifications: template <class T> struct remove_const; template <class T> struct remove_volatile; template <class T> struct remove_cv; template <class T> struct add_const; template <class T> struct add_volatile; template <class T> struct add_cv; // 20.6.6.2, reference modifications: template <class T> struct remove_reference; template <class T> struct add_lvalue_reference; template <class T> struct add_rvalue_reference; // 20.6.6.3, sign modifications: template <class T> struct make_signed; template <class T> struct make_unsigned; // 20.6.6.4, array modifications: template <class T> struct remove_extent; template <class T> struct remove_all_extents; // 20.6.6.5, pointer modifications: template <class T> struct remove_pointer; template <class T> struct add_pointer; // 20.6.7, other transformations: template <std::size_t Len, std::size_t Align> struct aligned_storage; template <std::size_t Len, class... Types> struct aligned_union; template <class T> struct decay; template <bool, class T = void> struct enable_if; template <bool, class T, class F> struct conditional; template <class... T> struct common_type; template <class T> struct underlying_type; } // namespace std
To 20.6.4.3 Type properties [meta.unary.prop], table Type property predicates, add rows:
Template Condition Preconditions template <class T>
struct is_trivially_copyable;T
is a trivially copyable type ([basic.types])T
shall be a complete type, an array of unknown bound, or (possibly cv-qualified)void
.template <class T>
struct is_literal_type;T
is a literal type ([basic.types])T
shall be a complete type, an array of unknown bound, or (possibly cv-qualified)void
.template <class T, class... Args> struct is_constructible; See below T and all types in the parameter pack Args shall be complete types, arrays of unknown bound, or (possibly cv-qualified) void types. template <class T, class... Args> struct is_nothrow_constructible; is_constructible<T, Args...>::value is true and the expression CE, as defined below, is known not to throw any exceptions. T and all types in the parameter pack Args shall be complete types, arrays of unknown bound, or (possibly cv-qualified) void types.
To 20.6.4.3 Type properties [meta.unary.prop], before table Type property queries, add:
Given the following function prototype:
template <class T> typename add_rvalue_reference<T>::type create();the predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied, if and only if the following expression CE would be well-formed:
- if sizeof...(Args) == 1 the expression:
static_cast<T>(create<Args>()...)- otherwise the expression:
T(create<Args>()...)
To 20.6.5 Relationships between types [meta.rel], table Type relationship predicates, add row:
Template Condition Comments template <class From, class To>
struct is_explicitly_convertible;is_constructible<To, From>::value is_explicitly_convertible
is a synonym for a two-argument is_constructible. An implementation may define it as a template alias.
To 20.6.7 Other transformations [meta.trans.other], table Other transformations, add row:
Template Condition Comments template <class T>
struct underlying_type;T shall be an enumeration type ([dcl.enum]) The member typedef type shall name the underlying type of the enum T.
Howard Hinnant, Lawrence Crowl, and Pablo Halpern contributed ideas and discussions leading to this proposal.