2013-07-18 11 views
16

Supponiamo di avereQual è la ragione alla base della mancanza di manipolazione del conteggio delle zecche immediata di std :: chrono :: duration?

#include <chrono> 
#include <iostream> 
#include <ctime> 

namespace Ratios { typedef std::ratio<60*60*24,1> Days; } 

typedef std::chrono::system_clock Clock; 
typedef Clock::time_point TimePoint; 

E la nostra main sembra

int main(int argc, char *argv[]) 
{ 
    // argc check left out for brevity 
    const Clock::rep d = static_cast<Clock::rep>(std::atoi(argv[1])); 
    // Right now 
    TimePoint now = Clock::now(); 
    // Start with zero days 
    auto days = std::chrono::duration<Clock::rep, Ratios::Days>::zero(); 

    // Now we'd like to add d to the days 
    days += d; // Error! 
    days.count() = d; // Error! 
    days = days + d; // Error! 
    days += std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay 
    days = days + std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay 

    days *= d; // Why is this okay? 
    days %= d; // And this too? 

    TimePoint later = now + days; 

    return 0; 
} 

Qual è il motivo dietro che vieta all'utente di manipolare un duration direttamente?

+0

Così tante buone risposte ... Posso solo accettarne una :) – rwols

risposta

23

Si fa in modo che ti impegni a rispettare valori fortemente tipizzati piuttosto che valori arbitrari.

Bjarne Stroustrup ha esempi riguardanti questo comportamento in "The C++ Programming Language" (4 ° Ed, 35.2.1, pp 1011..):


"Il periodo è un sistema di unità, quindi non c'è = o += prendendo un valore pianura ammettendo che sarebbe come permettere l'aggiunta di 5 di un'unità sI sconosciuto a una lunghezza in metri Considerare:..

duration<long long, milli> d1{7}; // 7 milliseconds 
d1 += 5; // error 
[...] 

Cosa significherebbe 5 qui? 5 secondi? 5 millisecondi? [...] Se sai cosa intendi, sii esplicito a riguardo. Ad esempio:

d1 += duration<long long, milli>{5}; //OK: milliseconds" 

1

Suppongo che ciò sia fatto per costringerti a considerare quali sono le unità della durata che vuoi aggiungere/sottrarre. Ti impedisce inoltre di formulare supposizioni su quali unità siano le tic tac dell'orologio.

13

La logica è quella di mantenere l'integrità della unità di tempo che rappresenta duration.

Si può pensare allo rep come senza unità. Ma lo duration ha un'unità di tempo. Si può aggiungere e sottrarre secondi a/da secondi. Ma non si possono aggiungere secondi e una quantità senza unità senza rendere l'espressione ambigua e violare l'algebra delle unità.

Detto questo, uno può moltiplicare e dividere un'unità di tempo di una quantità scalare (senza unità) e il risultato è ancora un'unità di tempo. Questa libreria rappresenta solo unità di tempo alla prima potenza, o potenza zero. Un'unità di tempo elevata alla potenza zero è uno scalare ed è rappresentata da rep. Le unità di tempo possono anche avere potenza di 2 o più e poteri negativi. Tuttavia questa libreria non rappresenta tali unità.

Quando si aggiungono due quantità, le unità devono essere uguali.

Quando si moltiplicano o dividono due quantità, viene formata una nuova unità (ad esempio km/h). Quando vengono moltiplicate le quantità delle stesse unità, i loro esponenti vengono aggiunti (ad es. Sec * sec == sec^2). Quando le quantità delle stesse unità vengono divise, i loro esponenti vengono sottratti (ad es. Sec/sec == sec^0 == uno scalare).

La biblioteca std::chrono::duration è un sottoinsieme consistente di una libreria fisica quantitativi che gestisce solo unità di tempo e solo quelle unità di tempo con esponente uguale a 0 e 1.

+0

Ovviamente il trattamento meraviglioso delle unità si interrompe quando si tratta di gestire zero, poiché zero è indipendente dalle unità. Naturalmente questa limitazione deriva da zero letterali che non hanno il loro tipo in C++ - è difficile accettare zero senza accettare scalari arbitrari. (Certo sarebbe bello poter dire 'if (d <0)' dove 'd' è comunque una certa durata.) –

8
days += d; // Error! 

Questo perché la variabile è days in unità di 86.400 secondi e la variabile d è senza unità. Il risultato dell'aggiunta di una quantità di un'unità a uno scalare senza unità non è definito nell'analisi dimensionale standard.

days *= d; // Why is this okay? 
days %= d; // And this too? 

Poiché moltiplicare e dividere le quantità per scalari senza unità non è privo di significato. Moltiplicando 2 secondi per 2 risultati in 4 secondi.

Considerare di moltiplicare 2 secondi per 3 secondi; il risultato è una quantità 6 con l'unità "secondi al quadrato". Ovviamente chrono::duration non è una libreria di unità completa, quindi non è possibile avere unità come il tempo al quadrato, ma le librerie come boost.units lo supporteranno.

Problemi correlati