MFC StopWatchクラス

ネタ元

takap-tech.com

// Stopwatch.hpp
// ネタ元:https://takap-tech.com/entry/2019/05/13/235416

#pragma once
// #pragma execution_character_set("utf-8")

#include <chrono>
#include <memory>

namespace diagnostics
{
    /**
     * C#の System.Stopwatch クラスっぽい動きをする時間測定クラス
     */
    class Stopwatch
    {
        // 動作しているかのフラグ
        // true : 動作中 / false : 停止中
        bool isRunning = false;
        // 測定開始時刻
        std::chrono::system_clock::time_point begin;
        // 測定開始時刻
        std::chrono::system_clock::time_point end;
        // 合計時間
        std::chrono::nanoseconds elapsed;

        Stopwatch() = default; // CreateNew or StartNewで作って!

    public:

        // 意味ないと思うのでmove以外禁止
        ~Stopwatch() = default;
        Stopwatch(const Stopwatch&) = delete;
        Stopwatch& operator=(const Stopwatch) = delete;
        Stopwatch(Stopwatch&&) = default;

        Stopwatch& operator=(Stopwatch&&) = default;

        bool getIsRunning() { return this->isRunning; }

        // 任意の型で計測時間を取り出す
        // Tempalte
        //   Unit  : 取得したい時間の型
        //   Ratio : 時間の単位
        template <typename Unit, class Ratio>
        Unit getElapsed()
        {
            if (this->isRunning)
            {
                return std::chrono::duration_cast<std::chrono::duration<Unit, Ratio>>(
                    std::chrono::system_clock::now() - this->begin).count(); // TooLong!!
            }
            else
            {
                return std::chrono::duration_cast<std::chrono::duration<Unit, Ratio>>(this->elapsed).count();
            }
        }

        // 経過時間を秒の倍精度浮動小数点として取り出す
        double getElapsedSeconds()
        {
            return this->getElapsed<double, std::ratio<1>>();
        }

        // 経過時間をミリ秒の倍精度浮動小数点として取り出す
        double getElapsedMilliseconds()
        {
            return this->getElapsed<double, std::milli>();
        }

        // 経過時間をナノ秒として取り出す
        long long getElapsedNanoseconds()
        {
            return this->getElapsed<long long, std::nano>();
        }

        void reset()
        {
            elapsed = std::chrono::nanoseconds(0);
            begin = end = std::chrono::system_clock::now();
        }

        void restart()
        {
            this->reset();
            this->start();
        }

        void start()
        {
            if (this->isRunning)
            {
                return;
            }

            this->isRunning = true;
            begin = end = std::chrono::system_clock::now();
        }

        void stop()
        {
            if (!this->isRunning)
            {
                return;
            }

            this->isRunning = false;
            end = std::chrono::system_clock::now();
            this->elapsed = this->elapsed + std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
        }

        static std::unique_ptr<Stopwatch> createNew()
        {
            std::unique_ptr<Stopwatch> sw(new Stopwatch());
            return sw;
        }

        static std::unique_ptr<Stopwatch> startNew()
        {
            auto sw = createNew();
            sw->start();
            return sw;
        }
    };
}


使い方

void Foo()
{
    // 時間測定を開始した状態でインスタンスを作成
    auto sw1 = diagnostics::Stopwatch::startNew();
    
    // ~~何らかの処理~~
    
    sw1->stop(); // 時間測定を停止
    
    // 結果を取得
    cout << "Elapsed(nano sec) = " << sw1->getElapsedNanoseconds() << endl;
    cout << "Elapsed(milli sec) = " << sw1->getElapsedMilliseconds() << endl;
    cout << "Elapsed(sec) = " << sw1->getElapsedSeconds() << endl;
    // > Elapsed(nano sec) = 74255700
    // > Elapsed(milli sec) = 74.2557
    // > Elapsed(sec) = 0.0742557
    
    sw1->reset(); // リセットして計測を再開
    sw1->start();
}