duration_castと浮動小数点数型

C++11から導入された時間ユーティリティライブラリChronoには、durationという経過時間を表す型があります。

この型の第1テンプレート引数には経過時間を表す数値型、第2テンプレートには単位を表すコンパイル有理数を指定します。

using milliseconds = duration<integer_type, ratio<1, 1000>>;
using seconds = duration<integer_type, ratio<1, 1>>;

この第2テンプレート引数を使って、ミリ秒から秒へ、秒からミリ秒へ、といった単位の変換ができます。

たとえば、1秒をミリ秒に変換すると、1000ミリ秒になります。

#include <cassert>
#include <chrono>

using namespace std::chrono;

int main()
{
    seconds a(1);
    milliseconds b = a;
    assert(b.count() == 1000);
}

逆に1000ミリ秒を秒に変換すると1秒になりますが、このときは精度が下がるため、1200ミリ秒を秒に変換すると1秒になり、200ミリ秒が失われます。このような、精度が下がる変換についてはdurationコンストラクタで直接は変換できないようになっています。代わりに、精度が下がる変換の場合には、duration_cast()という関数を通して変換を行います。

#include <cassert>
#include <chrono>

using namespace std::chrono;

int main()
{
    milliseconds a(1200);
    seconds b = duration_cast<seconds>(a);
    assert(b.count() == 1);
}

ここまでは、durationの内部表現が整数になっている場合です。次に、durationの内部表現を浮動小数点数型にしてみましょう。

using milliseconds_f = duration<float, ratio<1, 1000>>;
using seconds_f = duration<float, ratio<1, 1>>;

内部表現が浮動小数点数型の場合、精度が下がる変換をしても単に小数点以下の数値になるだけなので、duration_cast()を通さなくても単位変換ができます。

#include <iostream>
#include <chrono>

using namespace std::chrono;

using milliseconds_f = duration<float, std::ratio<1, 1000>>;
using seconds_f = duration<float, std::ratio<1, 1>>;

int main()
{
    milliseconds_f a(1200.0f);
    seconds_f b = a;

    std::cout << b.count() << std::endl;
}

出力:

1.2

durationコンストラクタの仕様については、以下のドキュメントを参照。

参照