A clock is four types, a flag and now()¶
Level: 201 · working knowledge
One line: The talk's first std::chrono slide is the whole definition of a clock — rep, period, duration, time_point, is_steady and now() — and writing one yourself gets you a clock a test can drive.
what_a_clock_is.cpp in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
// A clock is four types, a flag and a now(). This one only moves when you tell
// it to, which makes it the clock to hand a test — and makes this output exact.
#include <chrono>
#include <concepts>
#include <iostream>
#include <ratio>
namespace sc = std::chrono;
struct manual_clock {
using rep = long long; // what counts the ticks
using period = std::milli; // one tick is 1/1000 of a second
using duration = sc::duration<rep, period>; // a count of ticks
using time_point = sc::time_point<manual_clock>; // a duration since this clock's epoch
static constexpr bool is_steady = false; // advance() may be given a negative step
static time_point now() noexcept { return current; }
static void advance(duration step) noexcept { current += step; }
private:
static inline time_point current{}; // starts at its own epoch
};
// The requirements, as a concept. C++20 ships this check as
// std::chrono::is_clock_v, but libc++ 21 does not have it yet, so it is spelled
// out here — which is also the clearest statement of what a clock is.
template <class C>
concept a_clock = requires {
typename C::rep;
typename C::period;
typename C::duration;
typename C::time_point;
{ C::is_steady } -> std::convertible_to<bool>;
{ C::now() } -> std::same_as<typename C::time_point>;
};
int main() {
std::cout << std::boolalpha;
std::cout << "a_clock<manual_clock> = " << a_clock<manual_clock> << '\n'; // true
std::cout << "a_clock<sc::steady_clock> = " << a_clock<sc::steady_clock> << '\n'; // true
std::cout << "a_clock<int> = " << a_clock<int> << '\n'; // false
auto start = manual_clock::now();
manual_clock::advance(sc::milliseconds{1500});
auto stop = manual_clock::now();
std::cout << "stop - start = " << (stop - start) << '\n'; // 1500ms
std::cout << "since the epoch = " << stop.time_since_epoch() << '\n'; // 1500ms
std::cout << "one tick = " << manual_clock::period::num << '/'
<< manual_clock::period::den << " s\n"; // 1/1000 s
// The clock is part of the time point's type: this is not a steady_clock one.
std::cout << "same type as steady_clock's time_point = "
<< std::same_as<manual_clock::time_point, sc::steady_clock::time_point> << '\n'; // false
}
Verified output of what_a_clock_is.cpp — regenerated by tools/run_examples.py and held to the same answer key on libstdc++ and libc++ in CI, never hand-typed.
a_clock<manual_clock> = true
a_clock<sc::steady_clock> = true
a_clock<int> = false
stop - start = 1500ms
since the epoch = 1500ms
one tick = 1/1000 s
same type as steady_clock's time_point = false
The six members¶
This is the slide's some_clock, filled in. The standard lists the same six as the clock requirements (time.clock.req ↗):
| Member | What it is | The standard's words | In manual_clock |
|---|---|---|---|
rep |
the number that counts ticks | "An arithmetic type or a class emulating an arithmetic type" | long long |
period |
how long one tick is | "The tick period of the clock in seconds" — a std::ratio |
std::milli, 1/1000 s |
duration |
a count of ticks | duration<rep, period> |
built from the two above |
time_point |
a duration since this clock's epoch | time_point<C1> |
its own type |
is_steady |
never backwards, constant tick | "true if t1 <= t2 is always true and the time between clock ticks is constant" | false |
now() |
the current reading | "Returns a time_point object representing the current point in time" | whatever advance() made it |
Read the slide's /* period per s */ with care: period is seconds per tick, not ticks per second. std::milli is ratio<1, 1000> — a tick is a thousandth of a second — and steady_clock's std::nano is a billionth.
Why write a clock¶
- A test that controls time. Code that takes its clock as a template parameter can be handed
manual_clockin a test andsteady_clockin production. The test's timeouts become exact: the output above is deterministic because nothing in it waits for anything. - A counter that is not a clock yet. The talk's notes build a clock over the CPU's time-stamp counter, whose
periodhas to be the counter's frequency — the question that makesrdtschard, outlined in Reading the cycle counter. - A type the compiler keeps apart.
manual_clock::time_pointis notsteady_clock's — the last line of the output — so feeding one to code that expects the other is a compile error, for the reason on the next page.
is_steady is false here because advance() accepts a negative step. Nothing would stop you writing true: the flag is a promise the author makes, not something the library measures — Three clocks shows a real build whose steady_clock says true and reads the wall clock.
The slide's shorthand¶
The slide writes using duration = duration<rep, period>;, which assumes using namespace std::chrono. Made concrete, that is a program the standard calls ill-formed, no diagnostic required: inside a class, a name must mean the same thing where it is used as it does in the finished class (class.member.lookup ↗, paragraph 6), and here duration means std::chrono::duration on the right of the = and some_clock::duration from then on. "No diagnostic required" means a compiler may stay silent, and they disagree:
GCC 12.4 error declaration of 'using duration = …' changes meaning of 'duration' [-fpermissive]
GCC 13.4 warning declaration of 'using some_clock::duration = …' changes meaning of 'duration' [-Wchanges-meaning]
GCC 15.2 warning the same, and the same again for time_point
Clang 21.1 — compiles without a word
The fix is the one the standard library uses: qualify the name. libstdc++ writes typedef chrono::nanoseconds duration; inside system_clock (bits/chrono.h ↗), and manual_clock above writes sc::duration<rep, period>.
is_clock_v exists, but not everywhere yet¶
C++20 added std::chrono::is_clock_v<T> to ask whether T meets these requirements. libstdc++ has it — GCC 13.4 compiled a static_assert with it — but libc++ 21 does not: Apple clang 21 answered "no member named 'is_clock_v' in namespace 'std::chrono'" on 2026-09-10. So the example spells the question out as the concept a_clock, which also makes it the plainest statement of what a clock is.
If you are coming from another language¶
- Rust. The standard library has no clock trait:
InstantandSystemTimeare two concrete types, and code that wants a controllable clock defines a trait of its own. This page therefore has no Rust twin; the nearest is Two clocks: Instant and SystemTime ↗. - Python. No clock protocol either — a clock is a function that returns a
float, and a test swaps it by patching the function,unittest.mock.patch("time.monotonic"), where C++ swaps a type. - ABAP. (Not machine-checked.) The same testing problem is usually solved by wrapping
GET TIME STAMPin a class behind an interface and injecting a fake in the unit test —manual_clockas dependency injection.
See also¶
- Three clocks — the standard's three clocks against this checklist
- A time point knows its clock — the fourth type, and why it carries the clock
- A duration is a count and a unit —
repandperiod, from the duration's side - cppreference: the Clock requirements ↗