web-dev-qa-db-fra.com

Les objets std :: chrono :: duration infinis sont-ils légaux?

Est-il légal de fabriquer et d'utiliser std::chrono::duration<double> avec un infini comme valeur contenue, comme ça?

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

Se comportera-t-il "comme je m'y attendais", gardant une valeur infinie lors de l'ajout ou de la soustraction avec d'autres durées?

J'ai fouillé dans cppreference mais la seule chose que j'ai trouvée en discutant de la question est la page sur duration_cast en notant que:

La conversion d'une durée à virgule flottante en une durée entière est sujette à un comportement indéfini lorsque la valeur à virgule flottante est NaN, infini ou trop grande pour être représentable par le type entier de la cible. Sinon, la conversion en une durée entière est sujette à la troncature comme avec n'importe quel static_cast en un type entier.

ce qui semble impliquer que c'est légal, mais seulement d'une manière détournée.

(J'utilise le type pour représenter une méthode "Veuillez me réveiller en X secondes", et l'infini positif est une sentinelle utile pour représenter "Je m'en fiche vraiment quand je me réveille")

28
James Picone

La valeur infinity pour std::chrono::duration<double> Se comportera comme prévu avec les opérateurs arithmétiques.

std::chrono::duration<double> Est parfaitement bien

[time.duration] définit les conditions existantes sur Rep pour template<class Rep> std::chrono::duration et double est explicitement autorisé (par [time.duration ]/2 ), aucune valeur spéciale interdite:

Rep doit être un type arithmétique ou une classe émulant un type arithmétique.

std::numeric_limits<double>::infinity() est parfaitement bien

[time.duration.arithmetic] et [time.duration.nonmemberdefine] définissent le comportement des opérateurs arithmétiques sur duration. Pour chaque operator♦ Et pour deux objets durationA et B contenant les valeurs doublea et b, A♦B a les mêmes effets que a♦b. Par exemple pour +:

Dans les descriptions de fonctions qui suivent, CD représente le type de retour de la fonction. CR(A, B) représente 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);

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

Cela signifie explicitement que les éléments suivants se comporteront comme prévu:

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 };
14
YSC

Le trait duration_values a une valeur max() à cet effet:

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

N'utilisez pas infinity. Si vous deviez convertir une telle durée en un type basé sur des nombres entiers à l'avenir, vous pourriez vous retrouver avec UB.

3
rustyx