2017-06-19 7 views
5

J'ai besoin de convertir un type de std::chrono::duration en un autre type mais j'ai besoin de savoir quand une telle conversion est impossible car la valeur ne serait pas représentable.Comment vérifier le débordement dans duration_cast

Je n'ai trouvé aucune fonctionnalité dans la bibliothèque standard pour vérifier cela. Le cppreference page ne spécifie pas ce qui se passe si la valeur est en dehors de la plage, mais seulement que la conversion d'un nombre à virgule flottante en entier peut être un comportement indéfini (dans mon cas, j'ai besoin de convertir d'entier en entier).

Répondre

2

Il n'y a pas one-size-fits-all solution cependant une solution adaptée à de nombreux cas d'utilisation est d'utiliser un double à base duration pour la vérification de la plage. Peut-être quelque chose comme:

#include <chrono> 
#include <iostream> 
#include <stdexcept> 

template <class Duration, class Rep, class Period> 
Duration 
checked_convert(std::chrono::duration<Rep, Period> d) 
{ 
    using namespace std::chrono; 
    using S = duration<double, typename Duration::period>; 
    constexpr S m = Duration::min(); 
    constexpr S M = Duration::max(); 
    S s = d; 
    if (s < m || s > M) 
     throw std::overflow_error("checked_convert"); 
    return duration_cast<Duration>(s); 
} 

int 
main() 
{ 
    using namespace std::chrono; 
    std::cout << checked_convert<nanoseconds>(10'000h).count() << "ns\n"; 
    std::cout << checked_convert<nanoseconds>(10'000'000h).count() << "ns\n"; 
} 

Pour moi cette sortie:

36000000000000000ns 
libc++abi.dylib: terminating with uncaught exception of type std::overflow_error: checked_convert