std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
Questo è un ottimo posto per auto
:
auto now = std::chrono::system_clock::now();
Dal momento che si desidera traffico a millisecond
precisione, sarebbe bene andare avanti e segreto ad essa nella time_point
:
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
now_ms
è un time_point
, basato su system_clock
, ma con la precisione di milliseconds
invece di qualsiasi precisione abbia il tuo system_clock
.
auto epoch = now_ms.time_since_epoch();
epoch
ha ora digitare std::chrono::milliseconds
. E questa istruzione successiva diventa essenzialmente un no-op (semplicemente fa una copia e non fa una conversione):
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
Qui:
long duration = value.count();
Sia il vostro e il mio codice, duration
detiene il numero di milliseconds
dall'epoca di system_clock
.
Questo:
std::chrono::duration<long> dur(duration);
Crea un duration
rappresentato con un long
, e una precisione di seconds
. Ciò efficacemente reinterpret_cast
s milliseconds
detenuto in value
a seconds
. È un errore logico.Il codice corretto sarebbe simile:
std::chrono::milliseconds dur(duration);
Questa linea:
std::chrono::time_point<std::chrono::system_clock> dt(dur);
crea un time_point
basata su system_clock
, con la capacità di tenere una precisione di precisione nativo 's il system_clock
(in genere più fine di millisecondi). Tuttavia, il valore di runtime rispecchierà correttamente un numero intero di millisecondi (presupponendo la correzione sul tipo di dur
).
Anche con la correzione, questo test (quasi sempre) sicuro se:
if (dt != now)
Poiché dt
detiene un numero intero di milliseconds
, ma now
detiene un numero intero di zecche sottile di un millisecond
(es microseconds
o nanoseconds
). Pertanto, solo per la rara possibilità che system_clock::now()
abbia restituito un numero intero di milliseconds
, il test passerà.
Ma si può invece:
if (dt != now_ms)
E si avrà ora il risultato previsto in modo affidabile.
Mettere tutto insieme:
int main()
{
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
std::chrono::milliseconds dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
Personalmente trovo tutto il std::chrono
eccessivamente prolisso e quindi vorrei codificare come:
int main()
{
using namespace std::chrono;
auto now = system_clock::now();
auto now_ms = time_point_cast<milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
milliseconds dur(duration);
time_point<system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
che sarà affidabile di uscita:
Success.
Infine, consiglio di eliminare i provvisori per ridurre la conversione del codice tra time_point
e tipo integrale al minimo. Queste conversioni sono pericolosi, e così il codice meno si scrive manipolare il tipo integrale a nudo il meglio:
int main()
{
using namespace std::chrono;
// Get current time with precision of milliseconds
auto now = time_point_cast<milliseconds>(system_clock::now());
// sys_milliseconds is type time_point<system_clock, milliseconds>
using sys_milliseconds = decltype(now);
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
sys_milliseconds dt{milliseconds{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
Il pericolo principale di cui sopra è non interpretare integral_duration
come milliseconds
sulla via del ritorno a una time_point
. Un modo possibile per mitigare questo rischio è quello di scrivere:.
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
Questo riduce i rischi verso il basso per solo fare in modo di utilizzare sys_milliseconds
sulla via d'uscita, e nei due posti sulla via del ritorno in
E un altro esempio: supponiamo di voler convertire da un integrale che rappresenta la durata system_clock
(microsecondi, 10 th di microsecondi o nanosecondi). Quindi non devi preoccuparti di specificare millisecondi come sopra.Il codice semplifica a:
int main()
{
using namespace std::chrono;
// Get current time with native precision
auto now = system_clock::now();
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
system_clock::time_point dt{system_clock::duration{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
Questo funziona, ma se si esegue la metà la conversione (fuori a integrale) su una piattaforma e l'altra metà (in dal integrale) su un'altra piattaforma, si corre il rischio che system_clock::duration
sarà avere precisioni diverse per le due conversioni.
Non ho molta familiarità con la libreria chrono, ma credo che devi usare 'std :: chrono :: duration dur' e anche in questo caso potresti ottenere errori di arrotondamento (' std :: chrono :: system_clock' ha probabilmente una risoluzione maggiore di millisecondi). –
MikeMB