I'm calculating some changes in time over time using std::chrono::duration in order to obtain a approximation of a derative and trapezoid integral.
I would like to perform some common operations on a duration, but unfortunately failing to do so, probably because I do not understand chrono properly.
using std::chrono::milliseconds;
using namespace std;
milliseconds eightms = milliseconds(8);
milliseconds fourms = milliseconds(4);
milliseconds twoms = milliseconds(eightms / fourms); //<-- why do I need this cast?
milliseconds twoms = eightms / fourms;
cout << "twoms = " << twoms.count() << " ms" << endl;
expected output would be
twoms = 2 ms
If I do not use the cast above I get this for me cryptic compiler error, It works as expected when I cast the result of the division to milliseconds again.
dur_div_mult.cpp: In function ‘int main()’:
dur_div_mult.cpp:13:11: error: no match for ‘operator=’ (operand types are ‘std::chrono::milliseconds {aka std::chrono::duration<long int, std::ratio<1l, 1000l> >}’ and ‘std::__success_type<long int>::type {aka long int}’)
twoms = eightms/fourms;
^
In file included from dur_div_mult.cpp:2:0:
/usr/include/c++/5/chrono:274:12: note: candidate: std::chrono::duration<_Rep, _Period>& std::chrono::duration<_Rep, _Period>::operator=(const std::chrono::duration<_Rep, _Period>&) [with _Rep = long int; _Period = std::ratio<1l, 1000l>]
duration& operator=(const duration&) = default;
^
/usr/include/c++/5/chrono:274:12: note: no known conversion for argument 1 from ‘std::__success_type::type {aka long int}’ to ‘const std::chrono::duration >&’
Also multiplying 2ms * 4ms with results doesn't work as I would expect.
twoms = milliseconds(2);
fourms = milliseconds(4);
eightms = twoms * fourms;
cout << "eightms = " << eightms.count() << " ms" << endl;
expected output would be:
eightms = 8 ms
dur_div_mult.cpp: In function ‘int main()’:
dur_div_mult.cpp:18:21: error: no match for ‘operator*’ (operand types are ‘std::chrono::milliseconds {aka std::chrono::duration<long int, std::ratio<1l, 1000l> >}’ and ‘std::chrono::milliseconds {aka std::chrono::duration<long int, std::ratio<1l, 1000l> >}’)
eightms = twoms * fourms;
^
In file included from dur_div_mult.cpp:2:0:
/usr/include/c++/5/chrono:424:7: note: candidate: template<class _Rep1, class _Rep2, class _Period> constexpr std::chrono::duration<typename std::chrono::__common_rep_type<_Rep2, _Rep1>::type, _Period> std::chrono::operator*(const _Rep1&, const std::chrono::duration<_Rep, _Period>&)
operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d)
^
/usr/include/c++/5/chrono:424:7: note: template argument deduction/substitution failed:
/usr/include/c++/5/chrono: In substitution of ‘template<class _Rep1, class _Rep2, class _Period> constexpr std::chrono::duration<typename std::chrono::__common_rep_type<_Rep2, _Rep1>::type, _Period> std::chrono::operator*(const _Rep1&, const std::chrono::duration<_Rep, _Period>&) [with _Rep1 = std::chrono::duration<long int, std::ratio<1l, 1000l> >; _Rep2 = long int; _Period = std::ratio<1l, 1000l>]’:
dur_div_mult.cpp:18:23: required from here
/usr/include/c++/5/chrono:424:7: error: no type named ‘type’ in ‘struct std::common_type<long int, std::chrono::duration<long int, std::ratio<1l, 1000l> > >’
/usr/include/c++/5/chrono:414:7: note: candidate: template<class _Rep1, class _Period, class _Rep2> constexpr std::chrono::duration<typename std::chrono::__common_rep_type<_Rep1, _Rep2>::type, _Period> std::chrono::operator*(const std::chrono::duration<_Rep1, _Period1>&, const _Rep2&)
operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
^
/usr/include/c++/5/chrono:414:7: note: template argument deduction/substitution failed:
/usr/include/c++/5/chrono: In substitution of ‘template<class _Rep1, class _Period, class _Rep2> constexpr std::chrono::duration<typename std::chrono::__common_rep_type<_Rep1, _Rep2>::type, _Period> std::chrono::operator*(const std::chrono::duration<_Rep1, _Period1>&, const _Rep2&) [with _Rep1 = long int; _Period = std::ratio<1l, 1000l>; _Rep2 = std::chrono::duration<long int, std::ratio<1l, 1000l> >]’:
dur_div_mult.cpp:18:23: required from here
/usr/include/c++/5/chrono:414:7: error: no type named ‘type’ in ‘struct std::common_type<long int, std::chrono::duration<long int, std::ratio<1l, 1000l> > >’
Clearly I'm not using the std::chrono::duration correctly, but what am I doing wrong?
<chrono>
follows a strict subset of dimensional analysis rules.
A duration
has a unit of time. Let's ignore the precision of the units of time briefly and just refer to it generally as T
.
A scalar, (int
, double
, etc.), has no unit at all.
If you multiply two durations
together this would give you T
2 units (but this won't compile, keep reading). If you divide two durations
, you get a scalar: T
0. If you multiply a duration
by a scalar, you get T
1 (just time). If you divide a duration
by a scalar, you also get T
1 (just time). And if you divide a scalar by a duration
, you get T
-1, which is often referred to as a frequency (but this won't compile either).
<chrono>
provides that subset of physics where the result can be expressed either as T
1 (a duration
) or T
0 (a scalar). Other exponents are not allowed and result in compile-time errors. This isn't because they are wrong, but just outside the scope of this library.
eightms / fourms
results in the scalar 2
.
What you intend is:
milliseconds twoms = eightms / 4;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With