進捗率クラスを公開しました。
http://tricklib.com/cxx/dagger/progress.h
...そんなに分量ないし説明及びサンプルコードを含んでいるので 「続き」に内容を全て引用します。
モノとしては純粋に進捗率の計算を行う為だけのもので、boost の progress よりは boostっぽいかなぁと思います。
/****************************************************************************** Trick Library 'dagger' 進捗率クラスヘッダファイル Copyright(C) 2009 Wraith. All rights reserved. Coded by Wraith in Feb 6, 2009. ******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // ■ progress.h // http://tricklib.com/cxx/dagger/progress.h // // □ 関連ファイル // ありません。このファイルは単体で利用できます。 // // □ ライセンス情報 // http://tricklib.com/license.htm // #ifndef TRICKLIB_PROGRESS_H #define TRICKLIB_PROGRESS_H /////////////////////////////////////////////////////////////////////////////// // // デザインノート // // この進捗率クラスは進捗率の計算を行う為だけのものです。 // // ■構成 // // 予め総ステップ数が分かる場合に使用する rational_progress クラステンプ // レートと、処理が終わるまで総ステップ数が分からないような場合に使用する // infinite_progress クラステンプレートのみで構成されます。それ以外には何 // もありません。 // // ■使用上の注意 // // infinite_progress クラスのオブジェクトから rational_progress クラスの // オブジェクトに変換することが可能です(*1)が、この変換は進捗率をより的確 // に算出することを目的に行われる為、仮想的なステップ数(numerator)及び総 // ステップ数(denominator)が返されます。この為、変換されたオブジェクトお // よびそのオブジェクトを引数に構築された rational_progress クラスのオブ // ジェクトの numerator 及び denominator は仮想的な数値となります。 // // *1 infinite_progress<int_T, float_T>::operator rational_progress<int_T, float_T> () const /////////////////////////////////////////////////////////////////////////////// // // includes // #include <assert.h> /////////////////////////////////////////////////////////////////////////////// // // progress class templates // namespace tricklib { template<class int_T = int, class float_T = double> class rational_progress { public: typedef int_T element_type; typedef float_T result_type; typedef rational_progress this_type; int_T numerator; int_T denominator; rational_progress(const this_type & a) :numerator(a.numerator) ,denominator(a.denominator) { assert(0 < denominator); } rational_progress(int_T a_denominator) :numerator(0) ,denominator(a_denominator) { assert(0 < denominator); } rational_progress(int_T a_numerator, int_T a_denominator) :numerator(a_numerator) ,denominator(a_denominator) { assert(0 < denominator); } rational_progress(const this_type & minor, const this_type & major) :numerator((major.numerator *minor.denominator)+ minor.numerator) ,denominator(major.denominator *minor.denominator) { assert(0 < minor.denominator); assert(0 < major.denominator); assert(0 < denominator); assert(minor.denominator <= denominator); assert(major.denominator <= denominator); } this_type & operator = (const this_type & a) { numerator = a.numerator; denominator = a.denominator; return *this; } float_T current() const { assert(0 < denominator); return static_cast<float_T>(numerator) /static_cast<float_T>(denominator); } this_type & step(int_T inc_volume = 1) { numerator += inc_volume; return *this; } bool is_finished() const { return denominator <= numerator; } this_type & operator ++ () { return step(); } this_type operator ++ (int) { this_type temp(*this); step(); return temp; } }; template<class int_T = int, class float_T = double> class infinite_progress { public: typedef int_T element_type; typedef float_T result_type; typedef infinite_progress<int_T, float_T> this_type; int_T numerator; int_T half_volume; private: class infinite_progress_helper { public: int_T half_volume; int_T base_volume; int_T virtual_numerator; int_T virtual_denominator; infinite_progress_helper() :half_volume(0) ,base_volume(0) ,virtual_numerator(0) ,virtual_denominator(0) { } infinite_progress_helper(const infinite_progress_helper & a) :half_volume(a.half_volume) ,base_volume(a.base_volume) ,virtual_numerator(a.virtual_numerator) ,virtual_denominator(a.virtual_denominator) { } infinite_progress_helper & operator = (const infinite_progress_helper & a) { half_volume = a.half_volume; base_volume = a.base_volume; virtual_numerator = a.virtual_numerator; virtual_denominator = a.virtual_denominator; return *this; } }; mutable infinite_progress_helper cache; public: infinite_progress(const this_type & a) :numerator(a.numerator) ,half_volume(a.half_volume) ,cache(a.cache) { assert(0 < half_volume); } infinite_progress(int_T a_half_volume) :numerator(0) ,half_volume(a_half_volume) ,cache() { assert(0 < half_volume); } infinite_progress(int_T a_numerator, int_T a_half_volume) :numerator(a_numerator) ,half_volume(a_half_volume) ,cache() { assert(0 < half_volume); } this_type & operator = (const this_type & a) { numerator = a.numerator; half_volume = a.half_volume; cache = a.cache; return *this; } float_T current() const { return operator rational_progress<int_T, float_T> ().current(); } this_type & step(int_T inc_volume = 1) { numerator += inc_volume; return *this; } this_type & operator ++ () { return step(); } this_type operator ++ (int) { this_type temp(*this); step(); return temp; } operator rational_progress<int_T, float_T> () const { int_T rest = numerator; if (cache.base_volume <= rest && half_volume == cache.half_volume) { rest -= cache.base_volume; } else { cache.half_volume = half_volume; cache.base_volume = 0; cache.virtual_numerator = 0; cache.virtual_denominator = half_volume *2; } while(half_volume <= rest) { rest -= half_volume; cache.base_volume += half_volume; cache.virtual_numerator += half_volume; cache.virtual_numerator *= 2; cache.virtual_denominator *= 2; } return rational_progress<int_T, float_T>(cache.virtual_numerator +rest, cache.virtual_denominator); } }; } /////////////////////////////////////////////////////////////////////////////// // // サンプルコード // #if defined(TRICKLIB_PROGRESS_SAMPLE) //#include "progress.h" #include <stdio.h> #include <stdlib.h> #if defined(__WIN32__) || defined(_WIN32) #include <windows.h> void something() { Sleep(100); } #else #include <unistd.h> void something() { usleep(100000); } #endif using namespace tricklib; void funcA(rational_progress<> parent_progress, int * volumes); void funcB(rational_progress<> parent_progress, int * volumes); void funcC(rational_progress<> parent_progress, int * volumes); // 進捗率の表示 template<class int_T, class float_T> void print_progress(rational_progress<int_T, float_T> progress) { printf("進捗率: %3d%%\r", (int)(progress.current() *100.0)); } // シンプルなサンプル void funcA(rational_progress<> parent_progress, int * volumes) { // 現行レベル総ステップ数 int step_size = volumes[0]; // 親レベルの進捗率をベースにしたトータルの進捗率 rational_progress<> total_progress(rational_progress<>(step_size), parent_progress); for(int i = 0; i < step_size; ++i) { // 現行レベルの処理 something(); if (0 < volumes[1]) { // 子レベルの処理 funcB(total_progress, volumes +1); } // ステップカウントと進捗率の表示 ++total_progress; // 進捗率の表示 print_progress(total_progress); } } // トータルの進捗率と現行レベルの進捗率を別々に処理するサンプル void funcB(rational_progress<> parent_progress, int * volumes) { // 現行レベル総ステップ数 int step_size = volumes[0]; // 現行レベルの進捗率 rational_progress<> this_progress(step_size); // 親レベルの進捗率と現行レベルの進捗率のトータル rational_progress<> total_progress(this_progress, parent_progress); while(!this_progress.is_finished()) { // 現行レベルの処理 something(); if (0 < volumes[1]) { // 子レベルの処理 funcC(total_progress, volumes +1); } // ステップカウント ++this_progress, ++total_progress; // 進捗率の表示 print_progress(total_progress); } } // 現行レベルの総ステップ数が処理の終了時でないと分からない場合のサンプル void funcC(rational_progress<> parent_progress, int * volumes) { // 現行レベルの予想される平均的な総ステップ数の半分の値 int half_volume = 3; // 現行レベルの進捗率 infinite_progress<> this_progress(half_volume); // 親レベルの進捗率と現行レベルの進捗率のトータル rational_progress<> total_progress(this_progress, parent_progress); for(int i = 0; i < volumes[0]; ++i) { // 現行レベルの処理 something(); if (0 < volumes[1]) { // 子レベルの処理 funcA(total_progress, volumes +1); } // ステップカウント total_progress = rational_progress<>(++this_progress, parent_progress); // // ... infinite_progress を使用した場合、仮想的な総ステップ数が変化 // する為、この形でステップカウントを行う必要があります。 // // 尚、rational_progress の場合にもこの形でステップカウントを行っても // 構いません。 // 進捗率の表示 print_progress(total_progress); } } int main(int, char * []) { int volumes[] = { 5, 4, 3, 2, 0, }; // ルート進捗率 rational_progress<> root_progress(1); // 進捗率ゼロの表示 print_progress(root_progress); // 目的の処理 funcA(root_progress, volumes); // 完了の表示 print_progress(++root_progress); printf("\n"); return EXIT_SUCCESS; } #endif // defined(TRICKLIB_PROGRESS_SAMPLE) #endif // TRICKLIB_PROGRESS_H /****************************************************************************** □■□■ Wraith the Trickster □■□■ ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ ******************************************************************************/