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

### 955. Various threading bugs #5

Section: 29.3 [time.clock.req] Status: NAD Submitter: Pete Becker Opened: 2009-01-07 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [time.clock.req].

View all issues with NAD status.

Discussion:

29.3 [time.clock.req] requires that a clock type have a member typedef named `time_point` that names an instantiation of the template `time_point`, and a member named `duration` that names an instantiation of the template `duration`. This mixing of levels is confusing. The typedef names should be different from the template names.

[ Post Summit, Anthony provided proposed wording. ]

[ 2009-05-04 Howard adds: ]

> The reason that the typedef names were given the same name as the class templates was so that clients would not have to stop and think about whether they were using the clock's native `time_point` / `duration` or the class template directly. In this case, one person's confusion is another person's encapsulation. The detail that sometimes one is referring to the clock's native types, and sometimes one is referring to an independent type is purposefully "hidden" because it is supposed to be an unimportant detail. It can be confusing to have to remember when to type `duration` and when to type `duration_type`, and there is no need to require the client to remember something like that.

> For example, here is code that I once wrote in testing out the usability of this facility:

> >     template <class Clock, class Duration>
> >     void do_until(const std::chrono::time_point<Clock, Duration>& t)
> >     {
> >         typename Clock::time_point now = Clock::now();
> >         if (t > now)
> >         {
> >             typedef typename std::common_type
> >             <
> >                 Duration,
> >                 typename std::chrono::system_clock::duration
> >             >::type CD;
> >             typedef std::chrono::duration<double, std::nano> ID;

> >             CD d = t - now;
> >             ID us = duration_cast<ID>(d);
> >             if (us < d)
> >                 ++us;
> >             ...
> >         }
> >     }

> I see no rationale to require the client to append `_type` to some of those declarations. It seems overly burdensome on the author of `do_until`:

> >     template <class Clock, class Duration>
> >     void do_until(const std::chrono::time_point<Clock, Duration>& t)
> >     {
> >         typename Clock::time_point_type now = Clock::now();
> >         if (t > now)
> >         {
> >             typedef typename std::common_type
> >             <
> >                 Duration,
> >                 typename std::chrono::system_clock::duration_type
> >             >::type CD;
> >             typedef std::chrono::duration<double, std::nano> ID;

> >             CD d = t - now;
> >             ID us = duration_cast<ID>(d);
> >             if (us < d)
> >                 ++us;
> >             ...
> >         }
> >     }

> Additionally I'm fairly certain that this suggestion hasn't been implemented. If it had, it would have been discovered that it is incomplete. `time_point` also has a nested type (purposefully) named `duration`.

> > That is, the current proposed wording would put the WP into an inconsistent state.

> In contrast, the current WP has been implemented and I've received very favorable feedback from people using this interface in real-world code.

[ Batavia (2009-05): ]

> Bill agrees that distinct names should be used for distinct kinds of entities.

> Walter would prefer not to suffix type names, especially for such well-understood terms as "duration".

> Howard reminds us that the proposed resolution is incomplete, per his comment in the issue.

> Move to Open.

[ 2009-06-07 Howard adds: ]

> Not meaning to be argumentative, but we have a decade of positive experience with the precedent of using the same name for the nested type as an external class representing an identical concept.

> >     template<class Category, class T, class Distance = ptrdiff_t,
> >              class Pointer = T*, class Reference = T&>
> >     struct iterator
> >     {
> >         ...
> >     };

> >     template <BidirectionalIterator Iter>
> >     class reverse_iterator
> >     {
> >         ...
> >     };

> >     template <ValueType T, Allocator Alloc = allocator<T> >
> >         requires NothrowDestructible<T>
> >     class list
> >     {
> >     public:
> >         typedef implementation-defined     iterator;
> >         ...
> >         typedef reverse_iterator<iterator> reverse_iterator;
> >         ...
> >     };

> I am aware of zero complaints regarding the use of `iterator` and `reverse_iterator` as nested types of the containers despite these names also having related meaning at namespace std scope.

> Would we really be doing programmers a favor by renaming these nested types?

> >     template <ValueType T, Allocator Alloc = allocator<T> >
> >         requires NothrowDestructible<T>
> >     class list
> >     {
> >     public:
> >         typedef implementation-defined     iterator_type;
> >         ...
> >         typedef reverse_iterator<iterator> reverse_iterator_type;
> >         ...
> >     };

> I submit that such design contributes to needless verbosity which ends up reducing readability.

[ 2009-10 Santa Cruz: ]

> Mark as NAD. No concensus for changing the WP.

Proposed resolution:

Change 29 [time]:

>     ...
>     template <class Clock, class Duration = typename Clock::duration_type> class time_point;
>     ...

Change 29.3 [time.clock.req]:

> Table 45 -- Clock requirements
> Expression | Return type | Operational semantics
> --- | --- | ---
> ... | ... | ...
> `C1::duration_type` | `chrono::duration<C1::rep, C1::period>` | The native `duration` type of the clock.
> `C1::time_point_type` | `chrono::time_point<C1>` or `chrono::time_point<C2, C1::duration_type<` | The native `time_point` type of the clock. Different clocks may share a `time_point_type` definition if it is valid to compare their `time_point_type`s by comparing their respective `duration_type`s. `C1` and `C2` shall refer to the same epoch.
> ... | ... | ...
> `C1::now()` | `C1::time_point_type` | Returns a `time_point_type` object representing the current point in time.

Change 29.7.2 [time.clock.system]:

> -1- Objects of class `system_clock` represent wall clock time from the system-wide realtime clock.

> >     class system_clock {
> >     public:
> >       typedef see below rep;
> >       typedef ratio<unspecified, unspecified> period;
> >       typedef chrono::duration<rep, period> duration_type;
> >       typedef chrono::time_point<system_clock> time_point_type;
> >       static const bool is_monotonic = unspecified ;

> >       static time_point_type now();

> >       // Map to C API
> >       static time_t to_time_t (const time_point_type& t);
> >       static time_point_type from_time_t(time_t t);
> >     };

> -2- `system_clock::duration_type::min() < system_clock::duration_type::zero()` shall be `true`.

>     time_t to_time_t(const time_point_type& t);

> > -3- Returns: A `time_t` object that represents the same point in time as `t` when both values are truncated to the coarser of the precisions of `time_t` and `time_point_type`.

>     time_point_type from_time_t(time_t t);

> > -4- Returns: A `time_point_type` object that represents the same point in time as `t` when both values are truncated to the coarser of the precisions of `time_t` and `time_point_type`.

Change 99 [time.clock.monotonic]:

>     class monotonic_clock {
>     public:
>       typedef unspecified                                rep;
>       typedef ratio<unspecified , unspecified>           period;
>       typedef chrono::duration<rep, period>              duration_type;
>       typedef chrono::time_point<unspecified , duration_type> time_point_type;
>       static const bool is_monotonic =                   true;

>       static time_point_type now();
>     };

Change 29.7.8 [time.clock.hires]:

>     class high_resolution_clock {
>     public:
>       typedef unspecified                                rep;
>       typedef ratio<unspecified , unspecified>           period;
>       typedef chrono::duration<rep, period>              duration_type;
>       typedef chrono::time_point<unspecified , duration_type> time_point_type;
>       static const bool is_monotonic =                   true;

>       static time_point_type now();
>     };