I would do it like this:
template <class Rep, class Period>
std::chrono::duration<Rep, Period>
abs(std::chrono::duration<Rep, Period> d)
{
Rep x = d.count();
return std::chrono::duration<Rep, Period>(x >= 0 ? x : -x);
}
See my list of <chrono>
Utilities for other <chrono>
utilities I wish were standard. Please feel free to use them, recommend them to your standards body representatives, or propose them yourself.
Update
I was off my game when I wrote the above. I'm not deleting it, as it serves as a good lesson for both myself and others on how not to write chrono
utilities.
Things I don't like about it:
It needlessly drops type safety by directly manipulating the
Rep
.It assumes that the literal 0 is implicitly convertible to, or at least comparable with
Rep
.There is no reason for this not to be
constexpr
.I'm not happy about the behavior for unsigned
Rep
. If one says:auto d = abs(t1 - t0);
and t1
and t0
are based on unsigned durations, then this is likely a logic bug in the code. If t1 < t0
, then you are likely to get an incorrect, very large duration. If that is what you really want, then you shouldn't be using abs
, and instead just code the simpler:
auto d = t1 - t0;
To address these concerns I've rewritten abs
for durations as:
template <class Rep, class Period,
class = typename std::enable_if
<
std::chrono::duration<Rep, Period>::min() <
std::chrono::duration<Rep, Period>::zero()
>::type
>
constexpr
inline
std::chrono::duration<Rep, Period>
abs(std::chrono::duration<Rep, Period> d)
{
return d >= d.zero() ? d : -d;
}
duration
has unary-
, just use it.duration
has a customizablezero
trait just so that one doesn't have to assume an intimate cooperation with0
fromRep
. Just use it.All of the operations used are
constexpr
, markedabs
withconstexpr
.The static functions
min
andzero
areconstexpr
. Using these to determine ifRep
is signed is more general than using a trait such as!std::is_unsigned
. I.e.Rep
might be aBigNum
, or a C11timespec
(augmented with overloaded arithmetic operators). So the question "is signed" is answered withmin() < zero()
. And now this version ofabs
will not accept aduration<unsigned, milli>
(for example).