3

I have this test code:

#include <time.h>
#include <stdio.h>
#include <chrono>

namespace chrono = std::chrono;

int main()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);

    printf("time %ld.%09ld\n", ts.tv_sec, ts.tv_nsec);

    chrono::time_point<chrono::high_resolution_clock> t(chrono::seconds(ts.tv_sec));
    t += chrono::nanoseconds(ts.tv_nsec);

    chrono::seconds secs = chrono::duration_cast<chrono::seconds>(t.time_since_epoch());
    chrono::nanoseconds nsecs = chrono::duration_cast<chrono::nanoseconds>(t.time_since_epoch() - secs);

    printf("time %ld.%09ld\n", secs.count(), nsecs.count());
}

It compiles fine on an Ubuntu box with g++ 4.7.3 but on a Debian 7 box with 4.7.2 I get this compile output:

/home/atip/chronotest.cpp: In function ‘int main()’:
/home/atip/chronotest.cpp:15:40: error: no match for ‘operator+=’ in ‘t += std::chrono::duration<long int, std::ratio<1l, 1000000000l> >((*(const long int*)(& ts.timespec::tv_nsec)))’
/home/atip/chronotest.cpp:15:40: note: candidate is:
In file included from /home/atip/chronotest.cpp:3:0:
/usr/include/c++/4.7/chrono:550:2: note: std::chrono::time_point<_Clock, _Dur>& std::chrono::time_point<_Clock, _Dur>::operator+=(const duration&) [with _Clock = std::chrono::system_clock; _Dur = std::chrono::duration<long int, std::ratio<1l, 1000000l> >; std::chrono::time_point<_Clock, _Dur> = std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long int, std::ratio<1l, 1000000l> > >; std::chrono::time_point<_Clock, _Dur>::duration = std::chrono::duration<long int, std::ratio<1l, 1000000l> >]
/usr/include/c++/4.7/chrono:550:2: note:   no known conversion for argument 1 from ‘std::chrono::nanoseconds {aka std::chrono::duration<long int, std::ratio<1l, 1000000000l> >}’ to ‘const duration& {aka const std::chrono::duration<long int, std::ratio<1l, 1000000l> >&}’

Not sure how to decipher that, how do I get this working on both? Ultimately I have a function that gets a timespec and I want to convert that to a chrono::time_point, and then later convert it back.

Aaron
  • 1,141
  • 1
  • 11
  • 21

1 Answers1

3

Assuming both implementations are conforming.

Evidently on Ubuntu, the resolution of high_resolution_clock is nanoseconds or finer, but on Debian 7, the resolution of high_resolution_clock is courser than nanoseconds. The compile-time error prevents you from accidentally truncating the arithmetic:

t += chrono::nanoseconds(ts.tv_nsec);

to something where nanoseconds can not be accurately represented.

You can workaround this if you want by specifically requesting truncation if needed:

t += chrono::duration_cast<chrono::high_resolution_clock::duration>(chrono::nanoseconds(ts.tv_nsec));

This will truncate towards zero. Alternatively you could choose other rounding modes, though you would need to implement them yourself. Here is an example of a round-to-even algorithm for chrono::duration (search for "round").

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • Hmmm. Do I have to recompile libstdc++6 package to enable the nanosecond resolution clock? – Aaron Aug 17 '13 at 01:27
  • I don't know. It may simply be that it is not possible to support nanosecond resolution on that platform. The std::lib implementation is encouraged to support the highest resolution possible, and implementors are motivated to do so. But it typically needs support from the OS to accomplish that, and that may be missing. – Howard Hinnant Aug 17 '13 at 01:35
  • However you can write your own clocks in the `` library. Here is one I wrote that uses the Intel instruction `rdtsc` to implement a clock. http://stackoverflow.com/a/5524138/576911 . Not portable, but it is interoperable with the entire C++11 std::lib. – Howard Hinnant Aug 17 '13 at 01:40
  • Looks like Windows 7 when using Visual Studio 12 also defaults to something other than nanoseconds as the high_resolution duration. – Stéphane Oct 05 '14 at 20:02
  • great stuff, I was not aware of the resolution limitation and the compiler error is very obtuse. Is there anywhere these behaviors are documented? – yano Jun 06 '17 at 18:13
  • 1
    @yano: The "official documentation" is the C++ standard, which you can find various working drafts of here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/ Here is an excellent book on the entire std::lib, including chrono: http://www.cppstdlib.com And here is a free video tutorial on chrono: https://www.youtube.com/watch?v=P32hvk8b13M – Howard Hinnant Jun 06 '17 at 19:29