16

I just noticed the following code in <chrono.h>, which doesn't make sense to me.

struct system_clock
{
    static const bool is_monotonic = false; // retained
    static const bool is_steady = false;
};

class steady_clock
    : public system_clock
    {   // wraps monotonic clock
public:
    static const bool is_monotonic = true;  // retained
    static const bool is_steady = true;
    };

typedef steady_clock monotonic_clock;   // retained
typedef system_clock high_resolution_clock;

How can steady_clock be steady when it simply derives from system_clock which is not steady?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
ronag
  • 49,529
  • 25
  • 126
  • 221

3 Answers3

11

Ignoring the code you've shown (Jerry's answer already addresses that better than I could), presumably VC++ 2012's std::steady_clock is not steady, as evidenced by multiple bug reports currently open on MS Connect regarding this very issue:

ildjarn
  • 62,044
  • 9
  • 127
  • 211
10

Ignoring bugs in Microsoft's implementation for the moment, having a steady clock derive from an unsteady one (or a monotonic one derive from a non-monotonic one) makes perfectly good sense in general.

This is one of those places that the typical "is-a" terminology gets in the way, and you need to really think in terms of substitution instead. In particular, the situation is not "a steady clock is not an unsteady clock, so the derivation is wrong." Rather, the situation is "a steady clock can be substituted for an unsteady clock under any circumstances, so the derivation is fine" (and likewise for is_monotonic).

Let's consider an extreme example -- having an atomic clock connected directly to your computer. It's monotonic and about as steady as you can hope to get. Assuming its output is high enough frequency (/resolution), you could use it in place of essentially any/every other clock your system might have available.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    Right, this is interface inheritance, not implementation inheritance (although generally in C++ you might have both). And a steady clock satisfies the interface of an unsteady clock. – Ben Voigt Jul 15 '12 at 00:25
  • @BenVoigt I do not think "a steady clock satisfies the interface of an unsteady clock". `system_clock` supports `from_time_t` and `to_time_t`, which are not quite meaningful for a `steady_clock`. And a `steady_clock` or `high_resolution_clock` may not support the full range of `time_t` (esp. on 32-bit platforms). – Yongwei Wu Dec 31 '13 at 14:43
  • @YongweiWu: You are confusing steady vs unsteady with relative vs absolute time. – Ben Voigt Dec 31 '13 at 17:26
  • @BenVoigt: `steady_clock` does not guarantee whether it is relative or absolute. It can be either. What is your point? – Yongwei Wu Jan 01 '14 at 00:27
  • `Ignoring bugs in Microsoft's implementation for the moment` -- well said. That should be the default state. – kevinarpe Dec 23 '14 at 07:51
10

I actually do not agree with the "accepted answer". It is purely wrong on the Microsoft side, and can cause unrealistic expectations. The C++11 standard requires system_clock to implement to_time_t and from_time_t, but there are no such requirements for steady_clock and high_resolution_clock. It is not an "is-a" relationship, as steady_clock does not implement all required interfaces of system_clock; nor should it. Microsoft's action does not make sense to me: How can you expect a steady_clock has to_time_t while avoiding the problem of time skewing?

So, simply put, Microsoft made a mistake, and they are slow to fix it. According to Stephan T. Lavavej, he "didn't have time to fix this in 2013 RTM", and "all of the clocks need to be reimplemented, as tracked by several active bugs". See https://connect.microsoft.com/VisualStudio/feedback/details/719443/.

I guess it was not he that wrote the rubbish fake implementation in the beginning.

EDIT: I am a bit surprised that I got downvoted, even a little upset. My downvoters and disagreers, do you realize that you are rationalizing a broken implementation, which may be changed and fixed soon? Name me one real implementation that has steady_clock inherit from system_clock and is not broken....

FACT UPDATE in July 2014: As of Visual Studio 2014 CTP2, steady_clock no longer inherits from system_clock....

Yongwei Wu
  • 5,292
  • 37
  • 49
  • 2
    Missing the point again: while `steady_clock` doesn't need to have `to_time_t`, it certainly is allowed to. And there are no restrictions on how it gets `to_time_t`either, so inheritance from `system_clock` is OK too. – MSalters Dec 30 '13 at 17:46
  • 2
    @MSalters. You missed the point. Though `steady_clock` is allowed to implement `to_time_t`, there are no suitable semantics. What is more, it can make people write unportable code, which compiles only in MSVC, but not on other platforms--for example, if people really use `steady_clock` in where the interface requires a `system_clock&`. – Yongwei Wu Dec 31 '13 at 14:16
  • 1
    A quick Google search also revealed this link: http://stackoverflow.com/questions/18361638/converting-steady-clocktime-point-to-time-t. People said similar things: "`(to|from)_time_t` is meaningful only to system clocks. A `high_resolution_clock`, for example, may not be able to support the range of the whole `time_t`." – Yongwei Wu Dec 31 '13 at 14:26
  • Again, looking at Jerry Coffin's example of a computer directly connected to one of NIST's atomic clocks. It would be able to have a `steady_clock` implementation which is both steady and absolute, supports the entire range of times and conversion to/from `time_t`. the fact that *your* computer's steady-clock chip cannot do these things does not preclude the possibility. – Ben Voigt Dec 31 '13 at 17:29
  • 1
    @BenVoigt: Then you can say this atomic_clock satisfies both system_clock and steady_clock. Still, from the interface point of view, steady_clock should not be a system_clock. And it is a moot point in the case of a PC, as the system_clock is adjustable by any practical measures while steady_clock should not. They are incompatible types. Generally speaking, steady_clock is not Liskov-substitutable for system_clock. – Yongwei Wu Jan 01 '14 at 00:40