Constexpr Library Additions: chrono, v3

ISO/IEC JTC1 SC22 WG21 N3469 = 12-0159

2012-10-18

Benjamin Kosnik, bkoz@redhat.com

Daniel Krugler, daniel.kruegler@googlemail.com

Addresses or incorporates: LWG 2013, LWG 2054, and LWG 2057.

Informed by resolution of: LWG 2020

Introduction

This paper details use of the ISO C++0x constexpr feature, as initially introduced in “Generalized Constant Expressions — Revision 5” (N2235) and incorporating all other subsequent changes as per ISO C++ draft N3376. It is the first revision of N3303. Several CWG issues have also influenced the language with respect to constexpr: see issues 1099, 1125, 1194, 1195, 1197, 1198, 1199 and c++-std-core postings number 17890 and 17912. Additional implementation experience, and subsequent changes to the core language have motivated the following changes and additions to the library specification.

Proposed Changes

In a manner similar to the compile-time API provided via the standard’s <ratio> header, the following modifications provide a much larger compile-time interface to <chrono>. These modifications do not include signature changes, and are limited to either the addition of an opportune constexpr keyword or a subtle change to the required sematics to allow a generalized constant expression to be well-formed.

There are no ABI changes, and no run-time behavior changes.

A list of additional places in 20.11 Time Utilities aka std::chrono that can exploit the constexpr language feature is below. For the changes listed, the new text is put in place in bold and green with the older text it is replacing strucktohrugh in red.

Proposed wording

a) Modify 20.11.2 [time.syn]  as follows:

// 20.11.6.5, time_point arithmetic

template <class Clock, class Duration1, class Rep2, class Period2>

constexpr time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>

operator+(const time_point<Clock, Duration1>& lhs,

                  const duration<Rep2, Period2>& rhs);

template <class Rep1, class Period1, class Clock, class Duration2>

constexpr time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type>

operator+(const duration<Rep1, Period1>& lhs,

                  const time_point<Clock, Duration2>& rhs);

template <class Clock, class Duration1, class Rep2, class Period2>

constexpr time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>

operator-(const time_point<Clock, Duration1>& lhs,

                 const duration<Rep2, Period2>& rhs);

template <class Clock, class Duration1, class Duration2>

constexpr typename common_type<Duration1, Duration2>::type

  operator-(const time_point<Clock, Duration1>&,

      const time_point<Clock, Duration2>&);

// time_point comparisons

template <class Clock, class Duration1, class Duration2>

   constexpr bool operator==(const time_point<Clock, Duration1>& lhs,

                                             const time_point<Clock, Duration2>& rhs);

template <class Clock, class Duration1, class Duration2>

   constexpr bool operator!=(const time_point<Clock, Duration1>& lhs,

                                            const time_point<Clock, Duration2>& rhs);

template <class Clock, class Duration1, class Duration2>

   constexpr bool operator< (const time_point<Clock, Duration1>& lhs,

                                            const time_point<Clock, Duration2>& rhs);

template <class Clock, class Duration1, class Duration2>

   constexpr bool operator<=(const time_point<Clock, Duration1>& lhs,

                                            const time_point<Clock, Duration2>& rhs);

template <class Clock, class Duration1, class Duration2>

   constexpr bool operator> (const time_point<Clock, Duration1>& lhs,

                                            const time_point<Clock, Duration2>& rhs);

template <class Clock, class Duration1, class Duration2>

   constexpr bool operator>=(const time_point<Clock, Duration1>& lhs,

                                         const time_point<Clock, Duration2>& rhs);

// time_point_cast

template <class ToDuration, class Clock, class Duration>

  constexpr time_point<Clock, ToDuration>

  time_point_cast(const time_point<Clock, Duration>& t);

b) Add to 20.11.5 [time.duration]  after paragraph 6 as follows:

Remarks: The defaulted copy constructor of duration shall be a constexpr function if and only if the required initialization of the member rep_ for copy and move, respectively, would satisfy the requirements for a constexpr function.

c) Modify 20.11.6 [time.point] as follows:

constexpr time_point();

constexpr explicit time_point(const duration&);

template <class Duration2>

  constexpr time_point(const time_point<clock, Duration2>&);

constexpr duration time_since_epoch() const;

d) Modify 20.11.6.1 [time.point.cons] as follows:

constexpr time_point();

constexpr explicit time_point(const duration& d);

template <class Duration2>

  constexpr time_point(const time_point<clock, Duration2>& t);

e) Modify 20.11.6.2 [time.point.observer] as follows:

constexpr duration time_since_epoch() const;

f) Modify 20.11.6.5 [time.point.nonmember] as follows:

template <class Clock, class Duration1, class Rep2, class Period2>

constexpr time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>

operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);

Returns: CT(lhs) += rhs CT(lhs.time_since_epoch() + rhs) where CT is the type of the return value.

template <class Rep1, class Period1, class Clock, class Duration2>

constexpr time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type>

operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: rhs + lhs.

template <class Clock, class Duration1, class Rep2, class Period2>

constexpr time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>

operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);

Returns: lhs + (-rhs).

template <class Clock, class Duration1, class Duration2>

constexpr typename common_type<Duration1, Duration2>::type

operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: lhs.time_since_epoch() - rhs.time_since_epoch().

g) Modify 20.11.6.6 [time.point.comparisons] as follows:

template <class Clock, class Duration1, class Duration2>

constexpr bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: lhs.time_since_epoch() == rhs.time_since_epoch().

template <class Clock, class Duration1, class Duration2>

constexpr bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: !(lhs == rhs).

template <class Clock, class Duration1, class Duration2>

constexpr bool operator<(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: lhs.time_since_epoch() < rhs.time_since_epoch().

template <class Clock, class Duration1, class Duration2>

constexpr bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: !(rhs < lhs).

template <class Clock, class Duration1, class Duration2>

 constexpr bool operator>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: rhs < lhs.

template <class Clock, class Duration1, class Duration2>

constexpr bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: !(lhs < rhs).

h) Modify 20.11.6.7 [time.point.cast] as follows:

template <class ToDuration, class Clock, class Duration>

  constexpr time_point<Clock, ToDuration>

  time_point_cast(const time_point<Clock, Duration>& t);

Remarks: This function shall not participate in overload resolution unless ToDuration is an instanti-

 ation of duration.

Returns: time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch())).

i) Modify 20.11.7.1 [time.clock.system] as follows:

static const constexpr bool is_steady = unspecified;

j) Modify 20.11.7.2 [time.clock.steady] as follows:

static const constexpr bool is_steady = true;

k) Modify 20.11.7.3 [time.clock.hires] as follows:

static const constexpr bool is_steady = unspecified;

 

Acknowledgments

Many thanks to Jason Merrill, Paolo Carlini, and Jonathan Wakely for reviewing this document and providing assistance.