Cast chrono::milliseconds to uint64_t? - c++

Assuming I have the number of milliseconds in variable x:
chrono::milliseconds x = std::chrono::duration_cast<chrono::milliseconds>(something);
how do I convert x from chrono::milliseconds to uint64_t?
I have tried:
uint64_t num = std::chrono::duration_cast<uint64_t>(x);
but it says:
no matching function for call to
duration_cast(std::chrono::milliseconds&)

First of all, you generally shouldn't do this sort of thing. <chrono> provides a type-safe and generic units library for handling time durations, and there are few good reasons to escape this safety and genericity.
Some examples of the ills that don't happen with a type-safe, generic units library and which do happen with type-unsafe integral types:
// a type-safe units library prevents these mistakes:
int seconds = ...
int microseconds = seconds * 1000; // whoops
int time = seconds + microseconds; // whoops
void bar(int seconds);
bar(microseconds); // whoops
// a generic duration type prevents the need for:
unsigned sleep(unsigned seconds);
int usleep(useconds_t useconds);
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
int attosleep(long long attoseconds); // ???
// just use:
template<typename Duration>
int sleep_for(Duration t); // users can specify sleep in terms of hours, seconds, microseconds, femetoseconds, whatever. Actual sleep duration depends on QoI, as always.
An example of a good reason would be compatibility with a third party library that made the unfortunate decision not to use a type-safe, generic units library in their API. In this case the conversions should be done as close as possible to the API boundary in order to minimize the extent to which unsafe types are used.
So with that said, when you do have a good reason, you do so like this:
std::chrono::milliseconds x = ...
std::uint64_t num = x.count();
Keep in mind that the predefined chrono durations such as chrono::milliseconds use signed representations, so you'll need to take care to ensure the value is appropriate for conversion to uint64_t.

The prototype for std::chrono::duration_cast is:
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep,Period>& d);
You can't get an uint64_t directly, because it converts durations (duration_cast). So you need to create a std::duration with std::uint64_t.
using cast = std::chrono::duration<std::uint64_t>;
std::uint64_t ticks = std::chrono::duration_cast< cast >(something).count();

Related

Can a C++ union perform math on the number it contains?

Is it possible in C++ to create a union that would let me do something like this ...
union myTime {
long millis;
double seconds;
};
BUT, have it somehow do the conversion so that if I input times in milliseconds, and then call seconds, it will take the number and divide it by 1000, or conversely, if I input the number in seconds, then call millis, it would multiply the number by 1000...
So that:
myTime.millis = 1340;
double s = myTime.seconds;
Where s would equal 1.34
or
myTime.seconds = 2.5;
long m = myTime.millis;
Where m would = 2500
Is this possible?
A union is just different representations for the same value (the same bytes), so you can't define any smart logic over that.
In this case, you can define a class with conversion functions (both for initializtion or for getting the data).
class myTime {
public:
myTime(long millis);
double as_seconds();
static void from_seconds(double seconds);
};
Notice that as mentioned in other answers, for time conversions you can use std::chrono objects (c++11 and above)
To answer the question as asked: No. Unions are lower-level structure that simply allow multiple object representations to live in the same memory space. In your example, long and double share the same address.
They are not, however, smart enough to automatically do a conversation of any kind. Accessing the inactive member of a union is actually undefined behavior in most cases (there are exceptions for if you have a common-initial sequence in a standard-layout object).
Even if the behavior were well-defined, the value you would see in the double would be the double interpretation of the byte-pattern necessary to represent 1340.
If your problem is specifically to do with converting millis to seconds, as per your example, have you considered using std::chrono::duration units? These units are designed specifically for automatically doing these conversions between time units for you -- and you are capable of defining durations with custom representations (such as double).
Your example in your problem could be rewritten:
using double_seconds = std::chrono::duration<double>;
const auto millis = std::chrono::millis{1340};
const auto m = double_seconds{millis};
// m contains 1.340
You can if you abuse the type system a bit:
union myTime {
double seconds;
class milli_t {
double seconds;
public:
milli_t &operator=(double ms) {
seconds = ms/1000.0;
return *this; }
operator double() const { return seconds * 1000; }
} millis;
};
Now if you do
myTime t;
t.millis = 1340;
double s = t.seconds;
s would equal 1.34
and
myTime t;
t.seconds = 2.5;
long m = t.millis;
m would be 2500, exactly as you desire.
Of course, why you would want to do this is unclear.

comparing against time with chrono c++

I want to pretty much say "as long as we are under a certain time, continue to iterate"
the code for this looks like
int time = atoi(argv[1]);
auto start = std::chrono::high_resolution_clock::now();
while((std::chrono::duration_cast<chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count()) < time){
/*perform operation*/
}
However I am unable to compare against time like this and get the error error: conversion to ‘double’ from ‘std::chrono::duration<long int, std::ratio<1, 1000> >::rep {aka long int}’ may alter its value [-Werror=conversion]
does anyone know how to compare with the less than operator using chrono?
int time = atoi(argv[1]);
What units is time? seconds? nanoseconds? For this answer I'll assume seconds, but change it to whatever you need:
std::chrono::seconds time{atoi(arv[1])};
Next:
auto start = std::chrono::high_resolution_clock::now();
high_resolution_clock is going to be a type alias to either system_clock or steady_clock. The top of this answer explains the difference. I recommend chosing system_clock or steady_clock, depending on your needs, rather than letting the vendor choose for you.
while((std::chrono::duration_cast<chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count()) < time){
/*perform operation*/
}
Always try to stay within the chrono type system, instead of exiting it using .count(). Once you exit the chrono library, it can no longer help you. In this case it means doing the comparison using chrono units instead of ints.
When comparing chrono units, one does not need to cast such that both sides of the comparison are the same units. It is ok to compare seconds and milliseconds for example. chrono will do the comparison correctly, taking into account the different units.
I like to issue a function-scope using namespace std::chrono as I find repeated std::chrono:: overly verbose, making the code harder to read.
using namespace std::chrono;
seconds time{atoi(arv[1])};
auto start = steady_clock::now();
while(steady_clock::now() - start < time)
{
// perform operation
}
Or you can algebraically rearrange this:
while(steady_clock::now() < start + time)
{
// perform operation
}
Noticing the "constant" on the rhs, you can collect and rename that:
auto finish = steady_clock::now() + seconds{atoi(arv[1])};
while(steady_clock::now() < finish)
{
// perform operation
}
All of the above are equivalent, so you can choose whichever one you find more readable.
The error is in the precedence, you cast is performed after count() function, this cause that the cast is over a double value.
The problem can be solved in this way:
int time = atoi(argv[1]);
auto start = std::chrono::high_resolution_clock::now();
while(((std::chrono::duration_cast<chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start)).count()) < time){
/*perform operation*/
}

std::chrono calculate the difference in different ratio

My title may not be very helpful, I have an std::chrono::nanosecond, but I am asked to serialise and provide the second, and then the nanosecond as different values in a JSON.
So although my struct holds:
struct time
{
...
std::chrono::nanoseconds timepoint;
};
when asked for seconds, I do
uint32_t sec() const
{
return std::chrono::duration_cast<std::chrono::seconds>(timepoint_).count();
}
yet when asked for nanoseconds, I want the resolution in nanoseconds, but without the seconds (only the least significant values?) however, casting in nanoseconds returns both the seconds and the higher resolution.
uint64_t nanosec() const
{
return std::chrono::duration_cast<std::chrono::nanoseconds>(timepoint_).count();
}
How can I calculate the actual increased resolution (e.g., the nanoseconds without the actual seconds)?
You can retrieve the seconds using std::duration_cast to std::seconds and the nanoseconds using modulo operator:
template <typename T>
std::pair<T, T> split (std::chrono::duration<T, std::nano> const& duration) {
using seconds = std::chrono::duration<T>;
return {std::chrono::duration_cast<seconds>(duration).count(),
(duration % seconds{1}).count()};
}
There is a good example on this page showing the use of arithmetic operators on std::chrono::duration to achieve exactly what you want.
user #Xarn offered the solution:
auto sec = std::chrono::duration_cast<std::chrono::seconds>(tp);
auto nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(tp);
auto diff = std::chrono::duration_cast<std::chrono::nanoseconds>(nsec - sec).count();
leaves the nanosecond resolution without the seconds.

C++ chrono - get duration as float or long long

I have a duration
typedef std::chrono::high_resolution_clock Clock;
Clock::time_point beginTime;
Clock::time_point endTime;
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime);
And I get duration in std::chrono::milliseconds. But I need duration as float or long long. How to do that?
From the documentation
template<
class Rep,
class Period = std::ratio<1>
> class duration;
Class template std::chrono::duration represents a time interval. It
consists of a count of ticks of type Rep and a tick period, where the
tick period is a compile-time rational constant representing the
number of seconds from one tick to the next.
And:
count returns the count of ticks
So a duration stores a number of ticks of a specified period of time, and count will return that number using the underlying representation type. So if the duration's representation is long long, and the period is std::milli, then .count() will return a long long equal to the number of milliseconds represented by the duration.
In general you should avoid using weak types like float or long long to represent a duration. Instead you should stick with 'rich' types, such as std::chrono::milliseconds or an appropriate specialization of std::chrono::duration. These types aid correct usage and readability, and help prevent mistakes via type checking.
Underspecified / overly general:
– void increase_speed(double);
– Object obj; … obj.draw();
– Rectangle(int,int,int,int);
Better: – void increase_speed(Speed);
– Shape& s; … s.draw();
– Rectangle(Point top_left, Point bottom_right);
– Rectangle(Point top_left, Box_hw b);
— slide 18 from Bjarne's talk
std::chrono is "a consistent subset of a physical quantities library that handles only units of time and only those units of time with exponents equal to 0 and 1."
If you need to work with quantities of time you should take advantage of this library, or one that provides more complete unit systems, such as boost::units.
There are rare occasions where quantities must be degraded to weakly typed values. For example, when one must use an API that requires such types. Otherwise it should be avoided.
As float answer.
std::chrono's duration typedefs are integer. However, duration class can accept float.
See my duration typedefs:
https://github.com/faithandbrave/Shand/blob/master/shand/duration.hpp
...
template <class Rep>
using seconds_t = std::chrono::duration<Rep>;
using seconds_f = seconds_t<float>;
using seconds_d = seconds_t<double>;
using seconds_ld = seconds_t<long double>;
template <class Rep>
using minutes_t = std::chrono::duration<Rep, std::ratio<60>>;
using minutes_f = minutes_t<float>;
using minutes_d = minutes_t<double>;
using minutes_ld = minutes_t<long double>;
...
These durations usage is here:
#include <iostream>
#include <shand/duration.hpp>
int main()
{
std::chrono::seconds int_s(3);
shand::minutes_f float_m = int_s; // without `duration_cast`
std::cout << float_m.count() << std::endl; // 0.05
}

chrono with different time periods?

Currently I am using boost::rational<std::uint64> to keep track in my application.
Basically I have a clock that runs over a very long period of time and will be tick by different components of different time resolutions, e.g. 1/50s, 1/30s, 1001/30000s etc... I want to maintain perfect precision, i.e. no floating point. boost::rational works well for this purpose, however I think it would be better design to use std::chrono::duration for this.
My problem though is, how can I use std::chrono::duration here? Since it uses a compile time period I don't quite see how I can use it in my scenario where I need to maintain precision?
If I'm understanding your question, and if you know all of the different time resolutions at compile-time, then the following will do what you want. You can figure out the correct tick period by using common_type on all of your different time resolutions as shown below:
#include <cstdint>
#include <chrono>
struct clock
{
typedef std::uint64_t rep;
typedef std::common_type
<
std::chrono::duration<rep, std::ratio<1, 50>>,
std::chrono::duration<rep, std::ratio<1, 30>>,
std::chrono::duration<rep, std::ratio<1001, 30000>>
>::type duration;
typedef duration::period period;
typedef std::chrono::time_point<clock> time_point;
static const bool is_steady = true;
static time_point now()
{
// just as an example
using namespace std::chrono;
return time_point(duration_cast<duration>(steady_clock::now().time_since_epoch()));
}
};
This will compute at compile-time the largest tick period which will exactly represent each of your specified resolutions. For example with this clock one can exactly represent:
1/50 with 600 ticks.
1/30 with 1000 ticks.
1001/30000 with 1001 ticks.
The code below exercises this clock and uses the "chrono_io" facility described here to print out not only the run-time number of ticks of your clock, but also the compile-time units of your clock-tick:
#include <iostream>
#include <thread>
#include "chrono_io"
int main()
{
auto t0 = clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
auto t1 = clock::now();
std::cout << (t1-t0) << '\n';
}
For me this prints out:
633 [1/30000]seconds
Meaning: There were 633 clock ticks between calls to now() and the unit of each tick is 1/30000 of a second. If you don't want to be beholden to "chrono_io" you can inspect the units of your clock with clock::period::num and clock::period::den.
If your different time resolutions are not compile-time information, then your current solution with boost::rational is probably best.
You're allowed to set the period to 1 and use a floating point type for Rep.
I suspect that you can do the same thing with boost::rational, but you'll have to look quite closely at std::chrono, which I haven't done. Look at treat_as_floating_point and duration_values. Also try to figure out what the standard means by "An arithmetic type or a class emulating an arithmetic type".
One might reasonably argue that if boost::rational doesn't emulate an arithmetic type, then it's not doing its job. But it doesn't necessarily follow that it really does everything std::chrono::duration expects.