C++11 std::duration

目录

        • 一 chrono库
        • 二 duration
        • 三 成员类型
        • 四 Dem辅助函数
        • 五 成员函数
          • 1 构造函数
          • 2 count
          • 3 zero min max [static]
          • 4 operator+ operator-(unary)
          • 5 operator++ operator--
          • 6 compound assignment
        • 六 非成员函数
          • 1 算术运算
          • 2 关系运算
          • 3 duration_cast
          • 4 floor ceil round abs [C++17]
          • 5 operator<< 、from_stream [C++20]
        • 七 辅助类型
        • 八 辅助类
          • 1 std::common_type
          • 2 treat_as_floating_point
          • 3 duration_values
          • 4 std::formatter [C++20]
        • 九 字面量 [C++14]
        • 十 参考

一 chrono库

  • C++ 标准库chrono中有三个比较重要的概念,它们分别是:
    • clocks
    • time points
    • durations
  • 本文主要对 duration 概念进行讨论。

二 duration

  1. duration表示时间间隔或者说时间段,例如:42秒。42叫做tick数, 秒是单位。

A duration consists of a span of time, defined as some number of ticks of some time unit. For example, “42 seconds” could be represented by a duration consisting of 42 ticks of a 1-second time unit.

  1. 定义于头文件 < chrono >
template<class Rep, class Period = std::ratio<1>> 
class duration; (since C++11)
  • 由定义也能看出,duration 是一个数值和一个分数的组合。
    • 数值类型是Rep, 表示 tick数(计次数);
    • 分数表示时间单位,类型是具化的ration类型,默认是std::ratio<1>, 表示1秒。
  • std::ratio 请参考此前文章 C++11 std::ratio

三 成员类型

  • rep 表示计次类型
  • period 表示时间单位(计次周期)类型

四 Dem辅助函数

  • 下面Demo用到的辅助函数如下:
template<class DurationT>
void print(const std::string pre, const DurationT& d) {
  std::cout << "(" << pre << ")";
  std::cout << ".count(): " << d.count() << std::endl;
}

五 成员函数

1 构造函数
  • 定义
constexpr duration() = default;(1)(since C++11)
duration( const duration& ) = default;(2)(since C++11)
template< class Rep2 >
constexpr explicit duration( const Rep2& r );(3)(since C++11)
template< class Rep2, class Period2 >
constexpr duration( const duration<Rep2,Period2>& d );(4)(since C++11)
2 count
  • 返回计次数
  • Demo
std::chrono::duration<int, std::ratio<1,2>> d1 {10};
print("d1", d1);
  • 结果
(d1).count(): 10
3 zero min max [static]
  • 返回特殊duration值
  • Demo
std::chrono::duration<uint8_t, std::ratio<1>>::zero());
std::chrono::duration<uint8_t, std::ratio<1>>::min());
std::chrono::duration<uint8_t, std::ratio<1>>::max());
4 operator+ operator-(unary)
  • 一元加减
  • 定义
constexpr duration operator+() const;(1)(until C++17)
constexpr std::common_type_t<duration> operator+() const;(1)(since C++17)
constexpr duration operator-() const;(2)(until C++17)
constexpr std::common_type_t<duration> operator-() const;(2)(since C++17)
  • Demo
std::chrono::duration<int, std::ratio<1,2>> d1 {10};
print("d1", d1);
std::chrono::duration<int, std::ratio<1,2>> d2 = +d1;
print("d2", d2);
d2 = -d1;
print("d2", d2);
  • 结果
(d1).count(): 10
(d2).count(): 10
(d2).count(): -10
5 operator++ operator–
  • 递增、递减tick数
  • 定义
duration& operator++();(1)(C++17)
constexpr duration& operator++();(1)(C++17)	
duration operator++(int);(2)(C++17)
constexpr duration operator++(int);(2)(C++17)	
duration& operator--();(3)(C++17)
constexpr duration& operator--();(3)(C++17)	
duration operator--(int);(4)(C++17)
constexpr duration operator--(int);(4)(C++17)
  • Demo
std::chrono::duration<int, std::ratio<1, 2>> d1{10};
print("d1", d1);
print("d1++", d1++);
print("d1--", d1--);
print("++d1", ++d1);
print("--d1", --d1);
  • 结果
(d1).count(): 10
(d1++).count(): 10
(d1--).count(): 11
(++d1).count(): 11
(--d1).count(): 10
6 compound assignment
  • 两个duration复合赋值(+= -= *= /= %=)
  • 定义
duration& operator+=(const duration& d);(1)(until C++17)
constexpr duration& operator+=(const duration& d);(1)(since C++17)	
duration& operator-=(const duration& d);(2)(until C++17)
constexpr duration& operator-=(const duration& d);(2)(since C++17)	
duration& operator*=(const rep& rhs);(3)(until C++17)
constexpr duration& operator*=(const rep& rhs);(3)(since C++17)	
duration& operator/=(const rep& rhs);(4)(until C++17)
constexpr duration& operator/=(const rep& rhs);(4)(since C++17)
duration& operator%=(const rep& rhs);(5)(until C++17)
constexpr duration& operator%=(const rep& rhs);(5)(since C++17)	
duration& operator%=(const duration& rhs);(6)(until C++17)
constexpr duration& operator%=(const duration& rhs);(6)(since C++17)
  • Demo
std::chrono::duration<int, std::ratio<1, 2>> d1{1};
print("d1", d1);
std::chrono::duration<int, std::ratio<1, 3>> d2{1};
std::chrono::duration<int, std::ratio<1>> d3{1};
// d1 += d2; 不存在从d2 Period 到 d1 Period的隐式转换
// 通俗的说就是复合赋值的右变量不能是 "短" period
d1 += d3;
print("d1", d1);
  • 结果
(d1).count(): 1
(d1).count(): 3
  • 说明
    • d1 += d2隐式转换失败,但是通过duration_cast进行显式转换d2后可执行。见下。
  • 关于隐式转换

    Implicit conversions between two durations normally depends on the tick period of the durations.
    However, implicit conversions can happen regardless of tick period if std::chrono::treat_as_floating_point::value == true

    • treat_as_floating_point 见下面。

六 非成员函数

1 算术运算
  • 两个duration算术运算(+ - * / %)
  • 定义
template< class Rep1, class Period1, class Rep2, class Period2 >
typename std::common_type<duration<Rep1,Period1>, duration<Rep2,Period2>>::type
    constexpr operator+( const duration<Rep1,Period1>& lhs,
                         const duration<Rep2,Period2>& rhs );(1)	
template< class Rep1, class Period1, class Rep2, class Period2 >
typename std::common_type<duration<Rep1,Period1>, duration<Rep2,Period2>>::type
    constexpr operator-( const duration<Rep1,Period1>& lhs,
                         const duration<Rep2,Period2>& rhs );(2)	
template< class Rep1, class Period, class Rep2 >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
    constexpr operator*( const duration<Rep1,Period>& d, const Rep2& s );(3)	
template< class Rep1, class Rep2, class Period >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
    constexpr operator*( const Rep1& s, const duration<Rep2,Period>& d );(4)	
template< class Rep1, class Period, class Rep2 >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
    constexpr operator/( const duration<Rep1,Period>& d, const Rep2& s );(5)	
template< class Rep1, class Period1, class Rep2, class Period2 >
typename std::common_type<Rep1,Rep2>::type
    constexpr operator/( const duration<Rep1,Period1>& lhs,
                         const duration<Rep2,Period2>& rhs );(6)	
template< class Rep1, class Period, class Rep2 >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
    constexpr operator%( const duration<Rep1, Period>& d, const Rep2& s );(7)	
template< class Rep1, class Period1, class Rep2, class Period2 >
typename std::common_type<duration<Rep1,Period1>, duration<Rep2,Period2>>::type
constexpr operator%( const duration<Rep1,Period1>& lhs,
                     const duration<Rep2,Period2>& rhs );(8)
  • Demo
std::chrono::duration<int, std::ratio<1, 2>> d1{1};
print("d1", d1);
std::chrono::duration<int, std::ratio<1, 3>> d2{1};
print("d1+d2", d1 + d2);
std::cout << "typeid(decltype(d1+d2)).name(): " << std::endl 
          << typeid(decltype(d1+d2)).name() << std::endl;
print("d1-d2", d1 - d2);
print("2*d1", 2 * d1);
print("d2*2", d2 * 2);
std::cout << "d1/d2 : " << d1 / d2 << std::endl;  // 2
print("d1/2", d1 / 2);
print("d1%d2", d1 % d2);
print("d1%2", d1 % 2);
  • 结果
(d1).count(): 1
(d1+d2).count(): 5 // 1
typeid(decltype(d1+d2)).name():  // 1 
  class std::chrono::duration<int,struct std::ratio<1,6> >
(d1-d2).count(): 1
(2*d1).count(): 2
(d2*2).count(): 2
d1/d2 : 1  // 2
(d1/2).count(): 0
(d1%d2).count(): 1
(d1%2).count(): 1
  • 注意
    • 注意定义(6),两个duration相除是一个数值类型(结果2)
      • common_type见下面
    • 关于结果1
      • duration和 的单位是两个duration单位的最大公因数
      • 分数的最大公因数求解步骤:
        • 分数转换为假分数
        • 分子最大公因数/ 分母最小公倍数
          • 1/2 和 1/3 的最大公因数 = 1 / (2 * 3) = 1/6
          • 5/2 和 10/3 的最大公因数 = 5 / (2 * 3) = 5/6
2 关系运算
  • 两个duration关系运算(==,!=,<,<=,>,>=,<=>)
  • 定义
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator==(const std::chrono::duration<Rep1, Period1>& lhs,
               const std::chrono::duration<Rep2, Period2>& rhs);(1)(since C++11)
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator!=(const std::chrono::duration<Rep1, Period1>& lhs,
const std::chrono::duration<Rep2, Period2>& rhs);(2)(since C++11)(until C++20)
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<(const std::chrono::duration<Rep1, Period1>& lhs,
               const std::chrono::duration<Rep2, Period2>& rhs);(3)(since C++11)
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<=(const std::chrono::duration<Rep1, Period1>& lhs,
               onst std::chrono::duration<Rep2, Period2>& rhs);(4)(since C++11)
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>(const std::chrono::duration<Rep1, Period1>& lhs,
               const std::chrono::duration<Rep2, Period2>& rhs);(5)(since C++11)
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>=(const std::chrono::duration<Rep1, Period1>& lhs,
               const std::chrono::duration<Rep2, Period2>& rhs);(6)(since C++11)
template <class Rep1, class Period1, class Rep2, class Period2>
    requires std::three_way_comparable<std::common_type_t<Rep1, Rep2>>
constexpr auto operator<=>(const std::chrono::duration<Rep1, Period1>& lhs,
               const std::chrono::duration<Rep2, Period2>& rhs);(7)(since C++20)
  • Demo
std::chrono::duration<int, std::ratio<1, 2>> d1{1};
std::chrono::duration<int, std::ratio<1, 3>> d2{1};
std::cout << "d1==d2 : " << (d1==d2) << std::endl;
  • 结果
d1==d2 : 0
3 duration_cast
  • 显式转换duration
  • 定义
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep,Period>& d);(C++11)
  • 说明
    • 函数不参与重载决议,除非 ToDuration 是 std::chrono::duration 的实例
    • 在源duration能准确地为目标duration所整除的场合(例如小时到分钟),浮点时长和整数时长间转型能隐式进行,无需 duration_cast
    • 从浮点时长转型到整数时长,在浮点值为 NaN 、无穷大或过大而无法以目标的整数类型表示时,行为未定义
  • Demo
std::chrono::duration<int, std::ratio<1, 3>> d1{1};
auto d2 = std::chrono::duration_cast<std::chrono::duration<int,
                                     std::ratio<1, 10>>>(d1);
print("d2", d2);
  • 结果
(d2).count(): 3
4 floor ceil round abs [C++17]
  • floor向下取整;ceil向上取整;round就近取整,偶数优先;abs获取绝对值;
  • Demo
std::chrono::duration<int, std::ratio<1, 3>> d1{1};
auto d3 = std::chrono::floor<std::chrono::duration<int, 
                             std::ratio<1, 10>>>(d1);
print("d3", d3);
auto d4 =
std::chrono::ceil<std::chrono::duration<int, std::ratio<1, 10>>>(d1);
print("d4", d4);
auto d5 =
std::chrono::round<std::chrono::duration<int, std::ratio<1, 10>>>(d1);
print("d5", d5);
auto d5_1 =std::chrono::round<std::chrono::duration<int, 
                              std::ratio<1, 5>>>(d5);
print("d5_1", d5_1); 
std::chrono::duration<int, std::ratio<1, 3>> d6{-1};
auto d7 = std::chrono::abs(d6);
print("d7", d7);
  • 结果
(d3).count(): 3
(d4).count(): 4
(d5).count(): 3    // round 就近取整
(d5_1).count(): 2  // round 偶数优先
(d7).count(): 1
5 operator<< 、from_stream [C++20]

七 辅助类型

  • 定义了一些常用duration类型 (using别名)
    std::chrono::nanoseconds;
    std::chrono::microseconds;
    std::chrono::milliseconds;
    std::chrono::seconds;
    std::chrono::minutes;
    std::chrono::hours;
    // C++20
    // std::chrono::days 
    // std::chrono::weeks
    // std::chrono::months
    // std::chrono::years
  • Demo
std::this_thread::sleep_for(std::chrono::seconds(1));

八 辅助类

1 std::common_type
  • 确定两个duration的共用类型(std::common_type 特化)
  • Demo
std::chrono::seconds d1(1);
std::chrono::minutes d2(1);
typedef std::common_type<std::chrono::seconds,
                         std::chrono::minutes>::type type;
std::cout << typeid(type).name() << std::endl;
type d3(d2);
print("d3", d3);
  • 结果
class std::chrono::duration<__int64,struct std::ratio<1,1> >
(d3).count(): 60
2 treat_as_floating_point
  • 可用于duration转换判断
  • Demo
auto v = std::chrono::treat_as_floating_point<std::chrono::milliseconds::rep>::value;
3 duration_values
  • 定义Rep类型的3个特殊值(3个static方法)
  • 定义
template <class Rep>
struct duration_values;(C++11)
  • Demo
std::cout << std::chrono::duration_values<std::chrono::seconds::rep>::zero()  
          << std::endl;
std::cout << std::chrono::duration_values<std::chrono::seconds::rep>::min()  
          << std::endl;
std::cout << std::chrono::duration_values<std::chrono::seconds::rep>::max()  
          << std::endl;
  • 结果
0
-9223372036854775808
9223372036854775807
4 std::formatter [C++20]

九 字面量 [C++14]

  • 定义于内联命名空间 std::literals::chrono_literals

operator"“h(C++14) 表示小时的 std::chrono::duration 字面量
operator”“min(C++14) 表示分钟的 std::chrono::duration 字面量
operator”“s (C++14) 表示秒的 std::chrono::duration 字面量
operator”“ms(C++14) 表示毫秒的 std::chrono::duration 字面量
operator”“us(C++14) 表示微秒的 std::chrono::duration 字面量
operator”"ns(C++14) 表示纳秒的 std::chrono::duration 字面量

  • Demo
// 例子1
using namespace std::chrono_literals;
print("10h", 10h);
// 例子2
std::this_thread::sleep_for(1s);
  • 结果
// 例子1
(10h).count(): 10

十 参考

  • 《C++ 标准库 第2版》
  • cppreference - duration

你可能感兴趣的:(#,C++11/14/17/20)