std::chrono::duration<int,std::milli> IBM650_divide {15}; // A tick is 1 millisecond so 15 milliseconds std::chrono::duration<int> minute {60}; // A tick is 1 second by default so 60 seconds std::chrono::duration<double, ratio<60>>hour {60}; // A tick is 60 seconds so 60 minutes //A tick is a microsecond so 1 millisecond std::chrono::duration<long, std::micro> millisec {1000L}; //A tick is fifth of a second so 1.1 seconds std::chrono::duration<double, ratio<1,5>> tiny {5.5};第 1 條語句使用從 ratio 標頭檔案中獲取的對應於 ratio<1,1000> 的別名 milli。第 2 條語句省略了第二個模板引數的值,因此是 ratio<1>,這意味著持續時間以 1 秒為單位。
nanoseconds<integer_type, std::nano> microseconds<integer_type, std::micr>milliseconds<integer_type, std::milli> seconds<integer_type> minutes<integer_type, std::ratio<60>> hours<integer_type, std::ratio <3600>>
這些別名中,每個整數型別的持續時間值都取決於實現,但 C++14 標準要求 duration 至少為 292 年,可以是正數或負數。在筆者系統上小時和分鐘型別將 duration 儲存為 int 型別,將其他的儲存為 long long 型別。因此前面的程式碼段可以這樣定義 millisec 變數:std::chrono::microseconds millisec {1000}; // Duration is type long long on my system當然,這個定義和原始定義不同。變數的初值表示的是相同的時間間隔(1 毫秒)但這裡持續時間的單位是 1 毫秒,而在先前的程式碼中是 1 微秒。前面的 millisec 的定義許更精確地表示持續時間。
std::chrono:imilliseconds millisec {1}; // Duration is also type long long on my system第一個 += 運算的運算元為相同型別,作為右操作的物件所儲存的值會被加到左運算元上。第二個 += 運算的運算元為不同型別,但右運算元會被隱式轉換為左操作的型別。這是可能的,因為轉換是向有較短時間刻度的 duration 型別轉換的。如果向相反的方向轉換就不行,所以不能在 += 運算中用 long_time 作為左運算元、用 short_time 作為右運算元。
std::chrono::duration<double, ratio<1, 5>> tiny {5.5}; // Measured in 1/5 second std::chrono::microseconds very_tiny {100}; // Measured in microseconds ++tiny; very_tiny--; std::cout << "tiny = " << tiny.count()<< " very_tiny = " << very_tiny.count()<< std::endl; // tiny = 6.5 very_tiny = 99可以將任何二元算術運算子 +、-、*、/、% 應用到 duration 物件上,會得到一個 duration 物件作為結果。這些都是作為非成員運算子函數實現的。下面是一個範例:
std::chrono::duration<double, ratio<1, 5>> tiny {5.5}; std::chrono::duration<double, ratio<l, 5>> small {7.5}; auto total = tiny + small; std::cout << "total = " << total.count() << std::endl; // total = 13算術運算子也可以用不同型別的 std::chrono::duration<T,P> 模板範例作為運算元,模板的兩個引數都可以不同。這是通過使用 common_type<class... T> 模板的特化將兩個運算元轉換為它們的共有型別來實現的,common_type<class... T> 定義在 type_traits 標頭檔案中。對於 duration<T1,P1> 和 duration<T2, P2> 型別的引數,返回值為 duration 型別 duration<T3,P3>。T3 是 T1 和 T2 的共有型別。這些型別是通過將算術運算應用到這些型別的值來得到的。
std::chrono:imilliseconds ten_minutes {600000}; // A tick is 1 millisecond so 10 minutes std::chrono::minutes half_hour {30}; // A tick is 1 minute so 30 minutes auto total = ten_minutes + half_hour; // 40 minutes in common tick period std::cout <<"total = " << total.count()<< std::endl; // total = 2400000加法的結果是 40 分鐘,因此可以推斷出 total 是毫秒型別的物件。下面是另一個範例:
std::chrono::minutes ten_minutes {10}; // 10 minutes std::chrono::duration<double, std::ratio<1, 5>> interval {4500.0}; // 15 minutes auto total_minutes = ten_minutes + interval; std::cout << "total minutes = " << total_minutes.count()<< std::endl; // total minutes = 7500total_minutes 的值是 double 型別。我們知道結果必定是 25 分鐘,也就是 1500 秒;結果為 7500,因此時間刻度的長度為 ratio<1,5>,即 1/5 秒。最好盡可能地避免對混合的 duration 型別進行算術運算,因為很容易不知道時間刻度是什麼。
std::chrono::minutes short_time {20}; std::chrono::minutes shorter_time {10}; short_time += shorter_time; // 30 minutes std::chrono::hours long_time {3}; // 3hrs = 180 minutes short_time += long_time; std::cout << "short_time = " << short_time.count() << std::endl; // short_time = 210第一個 += 運算的運算元都為相同型別,因此右操作物件儲存的值會被加到左運算元上。第二個 += 運算的運算元為不同型別,但是右運算元可以隱式轉換為左運算元的型別。這是可能的,因為轉換的是短時鐘週期的 duration 型別。相反,就不能轉換,因此不能在用 += 時以 long_time 作為左運算元,以 short_time 作為右運算元。
std::chrono::duration<int, std::ratio<1, 5>> d1 {50}; // 10 seconds std::chrono::duration<int, std::ratio<1, 10>> d2 {50}; // 5 seconds std::chrono::duration<int, std::ratio<l, 3>> d3 {45}; // 15 seconds std::chrono::duration<int, std::ratio<1, 6>> d4 {60}; // 10 seconds d2 += d1; // OK - implicit conversion of d1 d1 += d2; // Won't compile 1/10 not a multiple of 1/5 d1 += d3; // Won't compile 1/3 not a multiple of 1/5 d4 += d3; //OK - implicit conversion of d3可以顯式地使用 dumtion_cast 模板進行強制轉換。下面是一個範例,假設 d1 和 d2 都有上述程式碼定義的初值:
d1 += std::chrono::duration_cast<std::chrono::duration<int, std::ratio<l, 5>>>(d2); std::cout << d1.count() << std::endl; // 75 - i.e.15 seconds第一條語句會用 duration_cast 來使 d2 加到 d1 的運算能夠進行。在這個範例中,結果是準確的,但並不總是如此。例如:
std::chrono::duration<int, std::ratio<1, 5>> d1 {50}; // 10 seconds std::chrono::duration<int, std::ratio<1, 10>> d2 {53}; // 5.3 seconds d1 += std::chrono::duration_cast<std::chrono::duration<int, std::ratio<1, 5>>>(d2); std::cout << d1.count() << std::endl; // 76 - i.e. 15.2 seconds不能將 duration 值 d1 和 d2 的和表示成 0.2 秒的整數倍,因此結果值稍微超出了。如果 d2 的值是 54,得到的正確結果應該是 77。
std::chrono::duration<int, std::ratio<1, 5>> d1 {50}; // 10 seconds std::chrono::duration<int, std::ratio<1, 10>> d2 {53}; // 5.3 seconds d2 = d1; // d2 is 100 = 10 seconds
std::chrono::duration<int,std::ratio<1, 5>> d1 {50}; // 10 seconds std::chrono::duratior<int, std::ratio<1, 10>> d2 {50}; // 5 seconds std::chrono::duration<int, std::ratio<1, 3>> d3 {45}; // 15 seconds if ((d1 - d2) == (d3 - d1)) std::cout << "both durations are "<<std::chrono::duration_cast<std::chrono::seconds〉(d1 - d2).count() << " seconds" << std::endl;這裡顯示了從算術運算得到的 duration 物件的比較方法。它們是相等的,當然也會產生這樣的輸出。seconds 型別的強制轉換允許秒數表示成整數,而不用管結果為 duration 型別。如果想使用非整數的秒數值,可以強制轉換為 dumtion<dcmble> 型別。
using namespace std::literals::chrono_literals;但是,如果指定了下面的宣告,上面的宣告會被自動包含:
using namespace std::chrono;可以將 duration 常數指定為整數或浮點值,字尾指定了時鐘週期。這裡有 6 個可以使用的字尾:
using namespace std::literals::chrono_literals; std::chrono::seconds elapsed {10}; // 10 seconds elapsed += 2min; // Adding type minutes to type seconds: 130 seconds elapsed -= 15s; // 115 seconds如範例所示,當需要改變間隔的長短時,duration 常數是非常有用的。需要記住的是,為了能夠進行算術運算,作為右運算元的時鐘週期必須是作為左運算元的時鐘週期的整數倍。例如:
elapsed += 100ns; // Won't compile!變數 lapsed 的時鐘週期為 1,不能向它加一個週期小於 1 的 duration。
auto some_time = 10s; // Variable of type seconds, value 10 elapsed = 3min - some_time;// Set to difference between literal and variable: result 170 some_time *= 2; // Doubles the value - now 20s const auto FIVE_SEC = 5s; // Cannot be changed elapsed = 2s + (elapsed - FIVE_SEC)/5; // Result 35這裡,some_time 是一個 seconds 型別的變數,它的型別為 duration<long long,ratio<1>>,值為 10。第 3 條語句說明可以改變 some_time 的值。FIVE_SEC 是 const seconds 型別的值,因此不能改變它的值。最後一條語句展示了一個包含一個 duration 常數、一個 duration 變數、一個常數型別的 seconds 物件,以及一個整數常數的算術表示式。