为什么C ++标准要求Clock :: now函数必须是静态的?

时间:2019-05-31 18:46:52

标签: c++ language-lawyer chrono

对于C ++ 11,C ++在标准中具有一些计时功能。这些功能之一是时钟的标准接口,基本上可以通过调用时钟的now函数来获取时间。

到目前为止,一切都很好,但是我看不出需要 now是静态函数的原因。在托管系统上,标准时钟可能仅通过系统调用或通过读取处理器计数器等即可实现。但是,这限制了需要维持某些状态的自定义时钟的实现。使用此接口,要么无法实现某些时钟,要么必须使用全局状态。

我遇到的一个问题是基本上将本地时钟与我从NTP服务器获得的时间同步。代码看起来像这样:

class sntp_clock
{
public:
    sntp_clock() 
        : local_time_at_ctor(read_some_cpu_counter())
        , sntp_time_at_ctor(read_sntp_time()) {}

    sntp_time_t now() const {
        return sntp_time_at_ctor + (read_some_cpu_counter() - local_time_at_ctor);
    }

    /* required types etc */

private:
    local_time_t local_time_at_ctor;
    sntp_time_t sntp_time_at_ctor;
};

由于我不能同时使now处于静态状态,因此该时钟无法满足C ++标准中 Clock 的要求。

此外,出于效率的考虑,我可能不想启动cpu计数器,而该时钟实例存在,但是同样,由于now是静态的,因此我无法确切知道何时开始计时或何时开始计时。停止它。

我的问题是,为什么时钟有静态的now要求?

注意:当前标准草案要求now是静态的:http://eel.is/c++draft/time.clock.req#tab:time.clock

Boost.Chrono文档具有相同的要求:https://www.boost.org/doc/libs/1_63_0/doc/html/chrono/reference.html#chrono.reference.cpp0x.clock

1 个答案:

答案 0 :(得分:10)

做出这一决定的因素既有理论性也有实践性。

理论

开个玩笑,一个有手表的人总是知道现在几点,但是有两个手表的人却永远不会知道。那个笑话只有一点点真相,而且确实影响了决定。如果应用程序需要知道两个或更多个位置的当前时间,并且时钟是有状态的,那么要确保在所有位置使用相同的时钟 instance 来确保代码的所有部分都使用相同的“当前时间”定义。

通过使时钟变为无状态,但允许使用不同类型的多个时钟,类型系统可以帮助程序员确保程序在程序的不同位置使用当前时间的相同定义。但是,在那些需要多个时间定义的情况下,那也可以使用,就像不同的类型一样。

实用

实际上,chrono::clock代码的第一个客户端是chrono本身。我们不得不吃自己的狗食。以condition_variable::wait_until的实现为例:

https://github.com/llvm-mirror/libcxx/blob/master/include/__mutex_base#L377-L385

template <class _Clock, class _Duration>
cv_status
condition_variable::wait_until(unique_lock<mutex>& __lk,
                               const chrono::time_point<_Clock, _Duration>& __t)
{
    using namespace chrono;
    wait_for(__lk, __t - _Clock::now());
    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
}

这里,一个函数采用单个通用time_point,算法需要找到与该time_point相关的当前时间。通过将Clock的类型打包到time_point的类型中,并通过拥有static now()来,该代码编写起来很干净,并且干净的界面。然而,足够通用的是,此代码可与任何用户编写的自定义时钟一起使用:而不仅仅是std指定的时钟。

如果时钟处于有状态状态,则可以:

  1. condition_variable::wait_until无法获取当前时间,或者
  2. 客户端也必须传递time_point的时钟。

以上两种选择对我来说都不是很好。

请注意,condition_variable::wait_until不是特例,只是许多此类算法中的一个示例。实际上,我假设不仅标准实施者会编写此类算法,而且公众也将编写此类算法。这是后者的示例:

https://stackoverflow.com/a/35293183/576911


是的,我遇到了人们想要有状态时钟的情况。这个问题的OP提供了这样一个例子。但是,由于可以选择“有状态的时钟”仍然可以设置为静态,因此,如果需要其他状态,请使用其他类型。并且由于上述无状态时钟的优点;选择的优势在于无状态时钟设计。