(11) is_clock_v , 为真时对 模板参数 T 的要求是什么:

++ 可见,系统定义的时钟类型,应该具有上图中的结构,下面是 is_clock_v 的定义:

++ 猜测,只要 void_t<T…> 的参数包中,有一个类型参数推断不出来,结果就不应该为 true 。 编写例子测试一下 vs2019 的 c++ 编译器的工作逻辑:

++ 补充 void_t<T…> 的工作原理:

(12) system_clock 源代码,因为这些常用的重要的类型的定义,所以单独列出,以便查阅:
// 系统时钟可以修改,甚至可以网络对时,因此使用系统时间计算时间差可能不准。
struct system_clock // 返回的是距离 1970 年的时间值
{
using rep = long long; // sizeof( long long ) = 8 字节
using period = ratio<1, 10'000'000>; // 100 nanoseconds = 100 纳秒
using duration = _CHRONO duration<rep, period>; // _CHRONO = ::std::chrono::
using time_point = _CHRONO time_point<system_clock>;
static constexpr bool is_steady = false;
// _CRTIMP2_PURE long long __cdecl _Xtime_get_ticks();
// 返回的是距离 1970 年的时间值, 以 100 纳秒 为单位
_NODISCARD static time_point now() noexcept // get current time
{
return time_point(duration(_Xtime_get_ticks()));
}
_NODISCARD static __time64_t to_time_t(const time_point& _Time) noexcept //拿到时间里的数值
{ // convert to __time64_t ; __time64_t = long long
return duration_cast<seconds>(_Time.time_since_epoch()).count();
}
// using seconds = duration<long long>; // 以 秒为计量单位
_NODISCARD static time_point from_time_t(__time64_t _Tm) noexcept // 构造一个时间值
{ // convert from __time64_t
return time_point{ seconds{_Tm} };
}
};
(13) steady_clock 的源代码:
//固定时钟,相当于秒表。开始计时后,时间只会增长并且不能修改,适合用于记录程序耗时
struct steady_clock // wraps QueryPerformanceCounter 返回的是本主机已经开机的时长,以 1 纳秒 为单位
{
using rep = long long;
using period = nano; // using nano = ratio<1, 1000000000>; 可见精度更高,纳秒
using duration = nanoseconds; // using nanoseconds = duration<long long, nano>;
using time_point = _CHRONO time_point<steady_clock>;
static constexpr bool is_steady = true;
// 本类只有这一个成员函数,返回的是本主机已经开机的时长,以 1 纳秒 为单位
_NODISCARD static time_point now() noexcept // get current time
{
const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot
const long long _Ctr = _Query_perf_counter ();
static_assert(period::num == 1, "This assumes period::num == 1.");
// 10 MHz是现代PC上非常常见的 QPC 频率。
// 优化该特定频率可以避免昂贵的频率转换路径,从而使该功能的性能翻倍。
constexpr long long _TenMHz = 10'000'000; // 定义了一个数, 10兆
if (_Freq == _TenMHz) {
static_assert(period::den % _TenMHz == 0, "It should never fail.");
constexpr long long _Multiplier = period::den / _TenMHz; // 等于 100
return time_point(duration(_Ctr * _Multiplier)); // 从 10^7 兆放大到纳秒,乘以 100
} else {
const long long _Whole = (_Ctr / _Freq) * period::den;
const long long _Part = (_Ctr % _Freq) * period::den / _Freq;
return time_point( duration(_Whole + _Part) );
}
}
};
using high_resolution_clock = steady_clock; // 和时钟类 steady_clock是等价的(是它的别名)。
(14) duration 时间值的 常见简化定义:
template <intmax_t _Nx, intmax_t _Dx = 1> // 默认分母为一
struct ratio {};
template < class _Rep, class _Period = ratio<1> >
class duration;
template <class _Rep, class _Period> // 代表一个时间持续时间
class duration
{
_Rep _MyRep; // 存储的时间值
template < class _Rep2 > // 有参构造函数
duration(const _Rep2& _Val) : _MyRep( static_cast<_Rep>(_Val) ) {}
}
using nanoseconds = duration<long long, nano>
using microseconds = duration<long long, micro>;
using milliseconds = duration<long long, milli>; // 以毫秒为计量单位
using seconds = duration<long long>; // 以 秒为计量单位
using minutes = duration<int, ratio<60>>; // 以 分为计量单位
using hours = duration<int, ratio<3600>>; // 以 时为计量单位
#if _HAS_CXX20
using days = duration<int, ratio_multiply<ratio<24>, hours::period>>; // 以 天 为计量单位 24*3600
using weeks = duration<int, ratio_multiply<ratio<7>, days::period>>; // 以 周 为计量单位
using years = duration<int, ratio_multiply<ratio<146097, 400>, days::period>>;
using months = duration<int, ratio_divide<years::period, ratio<12>>>; // 以 月 为计量单位
#endif // _HAS_CXX20
++ 以下给出 duration 的完整定义:
template <class _Rep, class _Period> // represents a time duration 代表一个时间持续时间
class duration
{
private:
_Rep _MyRep; // the stored rep
public:
using rep = _Rep; // 去掉了前置的下划线
using period = typename _Period::type; //= ratio<num, den>
// template <intmax_t _Nx, intmax_t _Dx = 1> // numerator 分子,被除数 ; denominator 分母
// struct ratio { using type = ratio<num, den>; }; // 这个 type 保存了简化版的比率
static_assert(!_Is_duration_v<_Rep>, "duration can't have duration as first template argument");
static_assert(_Is_ratio_v<_Period>, "period not an instance of std::ratio");
static_assert(0 < _Period::num, "period negative or zero"); // 时间只能往将来
// 默认构造函数
constexpr duration() = default;
template <class _Rep2, enable_if_t< // 把 _Rep2 类型的变量转换为 _Rep 类型存入类的数据成员
is_convertible_v<const _Rep2& , _Rep> &&
(treat_as_floating_point_v<_Rep> || !treat_as_floating_point_v<_Rep2>)
, int > = 0 >
constexpr explicit duration(const _Rep2& _Val) // 有参构造函数
noexcept( is_arithmetic_v<_Rep> && is_arithmetic_v<_Rep2>) // strengthened
: _MyRep(static_cast<_Rep>(_Val)) {}
// #define _CHRONO ::std::chrono::
// 此处 enable_if_t 的意思是,希望本类的数值是浮点类型;
// 若都是整数类型,则希望形参的 _Period2 可以更大,可以被本 duration 的计量周期整除。
template <class _Rep2, class _Period2, enable_if_t<
treat_as_floating_point_v< _Rep > || // 或,看来更喜欢本类的模板参数是浮点类型,数值范围更大
(_Ratio_divide_sfinae<_Period2, _Period>::den == 1 && !treat_as_floating_point_v<_Rep2> )
, int > = 0 >
constexpr duration(const duration<_Rep2, _Period2>& _Dur) // copy 构造函数
noexcept( is_arithmetic_v<_Rep> && is_arithmetic_v<_Rep2>)
: _MyRep(_CHRONO duration_cast<duration>(_Dur).count()) {}
// 返回存储的本类的数据成员
constexpr _Rep count() const noexcept(is_arithmetic_v<_Rep>) { return _MyRep; }
// 以下的成员函数,省略 constexpr 与 is_arithmetic_v<_Rep> 的判断,突出重点。
// 经测试,复杂的泛型推导,简单的结果:
// common_type_t< duration<int> > = duration<int>
// 取正与取负运算符: duration<int> a ; b = +a ; c = -a ; 就是此运算符函数
common_type_t<duration> operator+() { return common_type_t<duration>(*this); }
common_type_t<duration> operator-() { return common_type_t<duration>(-_MyRep); }
duration& operator++() { ++_MyRep ; return *this ; } // ++a
duration& operator--() { --_MyRep; return *this; } // --a
duration operator++(int) { return duration(_MyRep++); } // a++
duration operator--(int) { return duration(_MyRep--); } // a--
duration& operator+= (const duration& _Right) { _MyRep += _Right._MyRep; return *this; }
duration& operator-= (const duration& _Right) { _MyRep -= _Right._MyRep; return *this; }
duration& operator*= (const _Rep& _Right) { _MyRep *= _Right; return *this; }
duration& operator/= (const _Rep& _Right) { _MyRep /= _Right; return *this; }
duration& operator%= (const _Rep& _Right) { _MyRep %= _Right; return *this; }
duration& operator%= (const duration& _Right) { _MyRep %= _Right.count();return *this; }
static duration zero() { return duration( duration_values<_Rep>::zero() ); } // get zero value
static duration min () { return duration( duration_values<_Rep>::min() ) ; } // get minimum value
static duration max () { return duration( duration_values<_Rep>::max() ) ; } // get maximum value
};
(15) time_point ,表示某种时钟计时下的时间值:
// 第一个模板参数Clock用来指定所要使用的时钟,
// 标准库中有三种时钟,system_clock,steady_clock 和 high_resolution_clock 。
// 看定义可知,只需要指定模板类的模板参数一,第二个参数不指定的话就默认采用形参一里的计时单位
template <class _Clock, class _Duration = typename _Clock::duration>
class time_point // represents a point in time
{
private: // 先对数据成员初始化为 0
_Duration _MyDur{ duration::zero() }; // duration since the epoch 纪元以来持续的时间
public:
using clock = _Clock; // 类型定义,去掉了模板形参类名的前置下划线 _
using duration = _Duration; // 类型定义,去掉了模板形参类名的前置下划线 _
using rep = typename _Duration::rep;
using period = typename _Duration::period;
// template <class _Ty> // 测试 _Ty 是否是 duration 模板的子类
// constexpr bool _Is_duration_v = _Is_specialization_v<_Ty, duration>;
static_assert(_Is_duration_v<_Duration>, // N4885 ...l]/1授权 Duration为chrono::duration 的具体化。
"N4885 [time.point.general]/1 mandates Duration to be a specialization of chrono::duration.");
constexpr time_point() = default; // 默认的空的构造函数
// 以下开始省略多余的函数修饰符,突出重点
explicit time_point(const _Duration& _Other) : _MyDur(_Other) {} // 带参的构造函数
template <class _Duration2, enable_if_t<is_convertible_v<_Duration2, _Duration>, int> = 0>
time_point(const time_point<_Clock, _Duration2>& _Tp) // copy 构造函数
noexcept( is_arithmetic_v<rep> && is_arithmetic_v<typename _Duration2::rep>) // strengthened
: _MyDur(_Tp.time_since_epoch()) {}
_Duration time_since_epoch() { return _MyDur; } // 纪元,返回自己的数据成员的值
#if _HAS_CXX20
time_point& operator++() { ++_MyDur; return *this; } // ++a
time_point& operator--() { --_MyDur; return *this; } // --a
time_point operator++(int) { return time_point{ _MyDur++ }; } // a++
time_point operator--(int) { return time_point{ _MyDur-- }; } // a--
#endif // _HAS_CXX20
time_point& operator+=(const _Duration& _Dur) { _MyDur += _Dur; return *this; }
time_point& operator-=(const _Duration& _Dur) { _MyDur -= _Dur; return *this; }
static time_point min() { return time_point( _Duration::min() ); }
static time_point max() { return time_point( _Duration::max() ); }
};
(16)
谢谢
C++20 STL库时钟与时间相关源码解析
561

被折叠的 条评论
为什么被折叠?



