Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are infinite std::chrono::duration objects legal?

Is it legal to make and use std::chrono::duration<double>'s with an infinity as the contained value, like so?

std::chrono::duration<double>{ std::numeric_limits<double>::infinity() }; 

Will it behave 'like I expect', keeping an infinite value when adding or subtracting with other durations?

I've dug through cppreference but the only thing I've found discussing the question is the page on duration_cast noting that:

Casting from a floating-point duration to an integer duration is subject to undefined behavior when the floating-point value is NaN, infinity, or too large to be representable by the target's integer type. Otherwise, casting to an integer duration is subject to truncation as with any static_cast to an integer type.

which seems to imply that it's legal, but only in a backhanded sort of way.

(I'm using the type to represent a "Please wake me up in X seconds" way, and positive infinity is a useful sentinel to represent "I really don't care when I wake up")

like image 481
James Picone Avatar asked Mar 28 '18 06:03

James Picone


People also ask

What is std :: Chrono :: duration?

Class template std::chrono::duration represents a time interval. It consists of a count of ticks of type Rep and a tick period, where the tick period is a compile-time rational fraction representing the time in seconds from one tick to the next. The only data stored in a duration is a tick count of type Rep .

What is std :: Chrono :: seconds?

std::chrono::secondsInstantiation of duration to represent seconds.


2 Answers

The value infinity for std::chrono::duration<double> will behave as you expect with arithmetic operators.

std::chrono::duration<double> is perfectly fine

[time.duration] defines the conditions existing on Rep for template<class Rep> std::chrono::duration and double is explicitly allowed (per [time.duration]/2), no special value disallowed:

Rep shall be an arithmetic type or a class emulating an arithmetic type.

std::numeric_limits<double>::infinity() is perfectly fine

[time.duration.arithmetic] and [time.duration.nonmemberdefine] define the behaviour of the arithmetic operators on duration. For each operator♦ and given two duration objects A and B holding the double values a and b, A♦B effects as a♦b would. For instance for +:

In the function descriptions that follow, CD represents the return type of the function. CR(A, B) represents common_­type_­t<A, B>.

template<class Rep1, class Period1, class Rep2, class Period2>   constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>     operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); 

Returns: CD(CD(lhs).count() + CD(rhs).count()).

This explicitly means that the following will behave as expected:

const double infinity = std::numeric_limits<double>::infinity(); std::chrono::duration<double> inf{ infinity }; std::chrono::duration<double> one{ 1.0 }; inf + one; // as if std::chrono::duration<double>{ infinity + 1.0 }; 
like image 157
YSC Avatar answered Oct 11 '22 16:10

YSC


The duration_values trait has a max() value for that purpose:

    std::chrono::duration<double>::max(); 

Don't use infinity. Should you happen to convert such a duration to an integer-based type in the future, you can end up with UB.

like image 44
rustyx Avatar answered Oct 11 '22 17:10

rustyx