2016-03-04 1 views
-1

Est-ce que quelqu'un pourrait décrire le code suivant?C++ 11 instructions chronologiques

Merci

template<typename _Rep2, typename = typename 
     enable_if<is_convertible<_Rep2, rep>::value 
     && (treat_as_floating_point<rep>::value 
      || !treat_as_floating_point<_Rep2>::value)>::type> 
    constexpr explicit duration(const _Rep2& __rep) 
    : __r(static_cast<rep>(__rep)) { } 

template<typename _Rep2, typename _Period2, typename = typename 
     enable_if<treat_as_floating_point<rep>::value 
     || (ratio_divide<_Period2, period>::den == 1 
      && !treat_as_floating_point<_Rep2>::value)>::type> 
    constexpr duration(const duration<_Rep2, _Period2>& __d) 
    : __r(duration_cast<duration>(__d).count()) { } 
+0

Nous avons aucune idée de ce que vous voulez de cette question. Y a-t-il un problème avec le code? –

+0

Que voulez-vous exactement nous expliquer sur ce code? Personne n'a le temps d'écrire une analyse complète de cela. – jotik

Répondre

3

Ce sont les gcc/libstdC++ mise en œuvre des std::chrono::duration constructeurs. Nous pouvons les regarder un à la fois:

template <typename _Rep2, 
      typename = typename enable_if 
      < 
       is_convertible<_Rep2, rep>::value && 
       (treat_as_floating_point<rep>::value || 
       !treat_as_floating_point<_Rep2>::value) 
      >::type> 
constexpr 
explicit 
duration(const _Rep2& __rep) 
    : __r(static_cast<rep>(__rep)) 
    { } 

Le formatage aide à la lisibilité. Peu importe le style, tant qu'il en a. ;-)

Ce premier constructeur est constexpr et explicit, ce qui signifie que si les entrées sont des constantes de compilation, la durée de construction peut être une constante de compilation, et l'entrée ne sera pas implicitement se convertir à la durée.

Le but général de ce constructeur est explicitement convertir un scalaire (ou émulation d'un scalaire) en chrono::duration.

La deuxième typename dans la liste d'arguments modèle est une contrainte sur _Rep2. Il dit:

  1. _Rep2 doit être implicitement convertible en rep (rep est le type de représentation du duration), et

  2. Soit rep est un type à virgule flottante (ou émule un type à virgule flottante), ou _Rep2 n'est pas un type à virgule flottante (ou émulation d'un).

Si ces contraintes ne sont pas satisfaites, ce constructeur n'existe pas littéralement. L'effet de ces contraintes est que vous pouvez construire duration s à partir des arguments à virgule flottante et intégrale à virgule flottante, mais que les duration s doivent être construits à partir d'arguments entiers.

La raison d'être de cette contrainte est d'empêcher le rejet silencieux de la partie fractionnaire des arguments à virgule flottante. Par exemple:

minutes m{1.5}; // compile-time error 

Ce ne sera pas parce compilez minutes fait partie intégrante base, et l'argument est à virgule flottante, et si elle a effectivement compilé, il serait silencieusement jeter le .5 résultat 1min.

Maintenant pour le second constructeur chrono::duration:

template <typename _Rep2, 
      typename _Period2, 
      typename = typename enable_if 
      < 
       treat_as_floating_point<rep>::value || 
       (ratio_divide<_Period2, period>::den == 1 && 
       !treat_as_floating_point<_Rep2>::value) 
      >::type> 
constexpr 
duration(const duration<_Rep2, _Period2>& __d) 
    : __r(duration_cast<duration>(__d).count()) 
    { } 

Ce constructeur sert de conversion constructeur chrono::duration. C'est-à-dire qu'il convertit une unité en une autre (par exemple, hours à minutes).

De nouveau, il existe une contrainte sur les arguments de modèle Rep2 et Period2.Si ces contraintes ne sont pas satisfaites, le constructeur n'existe pas. Les contraintes sont les suivantes:

  1. rep est en virgule flottante, ou

  2. _Period2/period résultats dans un ratio avec un dénominateur de 1 et _Rep2 est un type entier (ou l'émulation de celui-ci).

L'effet de cette contrainte est que si vous avez une durée à virgule flottante, puis toute autre durée (intégrale ou à base de virgule flottante) va convertir implicitement à elle.

Toutefois, les durées basées sur l'intégrale sont beaucoup plus pointilleuses. Si vous convertissez à une durée à base intégrale, la durée de la source ne peut pas être point flottant basé et la conversion de la source la durée à base intégrale de la durée en fonction intégrale de destination doit être exacte. C'est-à-dire que la conversion ne doit pas diviser par un nombre quelconque sauf 1 (multiplier seulement).

Par exemple:

hours h = 30min; // will not compile 
minutes m = 1h; // ok 

Le premier exemple ne compile pas parce qu'elle nécessiterait une division par 60, ce qui h qui ne correspond pas à 30min. Mais le deuxième exemple compile car m sera exactement égal à 1h (il tiendra 60min).

Ce que vous pouvez enlever ceci:

  1. Toujours laissez <chrono> faire des conversions pour vous. Si vous multipliez ou divisez par 60 ou 1000 (ou peu importe) dans votre code, vous introduisez inutilement la possibilité d'erreurs. En outre, <chrono> vous indiquera si vous avez des conversions avec perte si vous déléguez toutes vos conversions au <chrono>.

  2. Utilisez autant que possible les conversions <chrono> implicites. Ils compileront et seront exacts, ou ils ne compileront pas. Si elles ne compilent pas, cela signifie que vous demandez une conversion qui implique une erreur de troncature. Vous pouvez demander une erreur de troncature, tant que vous ne le faites pas accidentellement. La syntaxe pour demander une conversion troncature est:

    hours h = duration_cast<hours>(30min); // ok, h == 0h 
    
+0

Merci beaucoup. Bonne explication. – xpath