Alisdair Meredith

2008-09-17

The original paper reviewing the language support library for application of
concepts was N2619. At the time the feature
was not understood well enough (by the author) to support the
`numeric_limits`

class template. In addition, the class template
`initializer_list`

has been added. This paper suggests constraints
for both templates.

There is a clear desire to use `numeric_limits`

from generic code,
as its key reason to exist is for code dealing with an arbitrary type to
probe for information.

An early mis-understanding in trying to understand this template is that there are really no constaints on the member functions themselves. While it is difficult to work out the necessary operations to compute the limitting values for arbitrary types, that is not how this template works. Instead, the basic implementation returns default values regardless of type, and an explicit specialization is expected for any type that is to be fully supported. Said specializations are not constrained to list the operations used in their implementations, as the specialization is effectively a regular class - there are no dependant names to look up.

There was some thought about defining a `NumericLimitType`

concept
so that default implementation could be supplied for the new members added to
the `numeric_limits`

template that could be found for valid
specializations according to the 03 specification. However, this seems a lot
of work for a look-up that will only occur in constrained contexts, for the
benefit of a couple of functions. A better approach would be to properly
decompose the numeric limits notion into a family of concepts that would
solve a more complete set of problems. That analysis is beyond this paper.

Finally, in order to constrain the `numeric_limits`

template a
reasonable requirement has to be chosen. The author has selected
`RegularType`

as possessing the right set of value-like
properties to represent an object that might be useful in a context
that we would want to query its numerical properties. This is also
a minimal set, to make implementation of the base template reasonable
without further constraints.

Initializer lists were added to support a unified syntax for initialization at the Sophia-Antipolis meeting, 2008. In order to support this syntax in constrained contexts, a minimal useful requirement is placed upon the template.

A further language feature targetting adoption in the CD to be issued from
the San Francisco meeting, 2008 is an enhanced for-loop syntax. This syntax
will be supported for `initializer_list`

s by providing a
concept_map for the `Range`

concept.

Finally, the `Container`

concept can also be supported by
`initializer_list`

with the addition of a few simple typedefs,
at least one of which is also needed to support the `Range`

concept.

Update 18.2.1.1 Class template numeric_limits [numeric.limits]

namespace std { template<~~class~~Regular T> class numeric_limits { public: static constexpr bool is_specialized = false; static constexpr T min() throw()~~;~~{ return T(); } static constexpr T max() throw()~~;~~{ return T(); } static constexpr T lowest() throw()~~;~~{ return T(); } static constexpr int digits = 0; static constexpr int digits10 = 0; static constexpr int max_digits10 = 0; static constexpr bool is_signed = false; static constexpr bool is_integer = false; static constexpr bool is_exact = false; static constexpr int radix = 0; static constexpr T epsilon() throw()~~;~~{ return T(); } static constexpr T round_error() throw()~~;~~{ return T(); } static constexpr int min_exponent = 0; static constexpr int min_exponent10 = 0; static constexpr int max_exponent = 0; static constexpr int max_exponent10 = 0; static constexpr bool has_infinity = false; static constexpr bool has_quiet_NaN = false; static constexpr bool has_signaling_NaN = false; static constexpr float_denorm_style has_denorm = denorm_absent; static constexpr bool has_denorm_loss = false; static constexpr T infinity() throw()~~;~~{ return T(); } static constexpr T quiet_NaN() throw()~~;~~{ return T(); } static constexpr T signaling_NaN() throw()~~;~~{ return T(); } static constexpr T denorm_min() throw()~~;~~{ return T(); } static constexpr bool is_iec559 = false; static constexpr bool is_bounded = false; static constexpr bool is_modulo = false; static constexpr bool traps = false; static constexpr bool tinyness_before = false; static constexpr float_round_style round_style = round_toward_zero; }; ... }

Update 18.8 Initializer lists [support.initlist]p1

namespace std { template<~~class~~ObjectType E> class initializer_list { public: typedef E value_type; typedef const E& reference; typedef const E& const_reference; typedef size_t size_type; typedef const E * iterator; typedef const E * const_iterator; initializer_list(); size_t size() const; // number of elements const E* begin() const; // first element const E* end() const; // one past the last element }; template<ObjectType T> concept_map Range<initializer_list<T>> { const T * begin( initializer_list<T> c ) { return c.begin(); } const T * end( initializer_list<T> c ) { return c.end(); } }; }