Constexpr Library Additions: chrono, v2
ISO/IEC JTC1 SC22 WG21 N3303 = 11-0073 - 2011-08-20
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 N3291. It is the first revision of N3229. 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.
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 struckthrough 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) Modify 20.11.5 [time.duration] as follows:
constexpr duration() = default;
constexpr duration(const duration&) = default;
c) Modify 20.11.5.1 [time.duration.cons] as follows:
constexpr duration();
Effects: Constructs an object of type duration, value initializing rep_.
Note: [Scalars do not have constexpr default constructors. This is problematic when used as member data for duration, as constexpr defaulted constructors are only well formed for classes where all member data have constexpr default constructors.]
d) 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;
e) 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);
f) Modify 20.11.6.2 [time.point.observer] as follows:
constexpr duration time_since_epoch() const;
g) 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().
h) 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).
i) 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())).
j) Modify 20.11.7.1 [time.clock.system] as follows:
static const constexpr bool is_steady = unspecified;
k) Modify 20.11.7.2 [time.clock.steady] as follows:
static const constexpr bool is_steady = unspecified;
l) 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.