```
template<class Rep> struct treat_as_floating_point : is_floating_point<Rep> { };
```

The duration template uses the treat_as_floating_point trait to
help determine if a duration object can be converted to another
duration with a different tick period.

If
treat_as_floating_point_v<Rep> is true, then implicit conversions
are allowed among durations.

[â€‰Note

: *end note*

â€‰]The intention of this trait is to indicate whether a given class behaves like a floating-point
type, and thus allows division of one value by another with acceptable loss of precision.

If
treat_as_floating_point_v<Rep> is false, Rep will be treated as
if it behaved like an integral type for the purpose of these conversions.

â€”â€‰```
template<class Rep>
struct duration_values {
public:
static constexpr Rep zero() noexcept;
static constexpr Rep min() noexcept;
static constexpr Rep max() noexcept;
};
```

The duration template uses the duration_values trait to
construct special values of the duration's representation (Rep).

This is
done because the representation might be a class type with behavior which
requires some other implementation to return these special values.

In that case,
the author of that class type should specialize duration_values to
return the indicated values.

```
static constexpr Rep zero() noexcept;
```

```
static constexpr Rep min() noexcept;
```

```
static constexpr Rep max() noexcept;
```

```
template<class Rep1, class Period1, class Rep2, class Period2>
struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>> {
using type = chrono::duration<common_type_t<Rep1, Rep2>, see below>;
};
```

The period of the duration indicated by this specialization of
common_type shall be the greatest common divisor of Period1 and
Period2.

[â€‰Note

: *end note*

â€‰]The typedef name type is a synonym for the
duration with the largest tick period possible where both
duration arguments will convert to it without requiring a division
operation.

The representation of this type is intended to be able to hold any
value resulting from this conversion with no truncation error, although
floating-point durations may have round-off errors.

â€”â€‰```
template<class Clock, class Duration1, class Duration2>
struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>> {
using type = chrono::time_point<Clock, common_type_t<Duration1, Duration2>>;
};
```

```
template<class T> struct is_clock;
```

is_clock is a Cpp17UnaryTypeTrait ([meta.rqmts])
with a base characteristic of true_type
if T meets the Cpp17Clock requirements ([time.clock.req]),
otherwise false_type.

For the purposes of the specification of this trait,
the extent to which an implementation determines
that a type cannot meet the Cpp17Clock requirements is unspecified,
except that as a minimum
a type T shall not qualify as a Cpp17Clock
unless it meets all of the following conditions:

- the
*qualified-id*s T::rep, T::period, T::duration, and T::time_point are valid and each denotes a type ([temp.deduct]), - the expression T::is_steady is well-formed when treated as an unevaluated operand,
- the expression T::now() is well-formed when treated as an unevaluated operand.