/****************************************************************************** Trick Library 'dagger' tips モジュールヘッダファイル Copyright(C) 2002 Wraith. All rights reserved. Coded by Wraith in Feb 3, 2002. Last Update in Feb 6, 2002. ******************************************************************************/ // Tab幅を4文字に設定して表示させてください。 // ■ tips.h // source location: http://tricklib.com/cxx/dagger/tips.h // // □ 関連ファイル // ありません。このファイルは単体で利用できます。 #ifndef __TrickLibrary_TIPS_H__ #define __TrickLibrary_TIPS_H__ // ■ TrickLibrary 'dagger' tips モジュール // // TrickLibrary は道化師の提供するフリーのライブラリで、'dagger' // は環境非依存の C++ 用ライブラリです。 // // # MS-Windows 用基本セットが 'rapier' で、同フルセットが 'javelin'。 // # ... などと言いつつこの二つが世に出回る(公開される)ことはおそ // # らくないと思います。(^^; できるならこれらをリリースしつつ他 // # のプラットフォーム( Mac, Linux )用のライブラリもリリースして // # いきたいものですが。 // // この tips モジュールは主に cppll ML での投稿を元に拡張して行 // く予定です。 // // cf. [cppll ML] http://www.trickpalace.net/cppll/ // // □ 'USING_TRICKLIB' マクロについて // // 'USING_TRICKLIB' マクロを宣言しておけばこのライブラリ中のマク // ロが短い形式( 'tricklib_' を省略した形 )で利用できます。 // // □ 'ギミック' について // // マクロやテンプレートなどを複数組み合わせることで一つの機能を成 // しているものをここでは 'ギミック' と呼ぶことにします。 // #include #include namespace tricklib { // // ■ コンパイラの仕様識別マクロ // // おいらが調査不足のコンパイラを使用されているかたは悪いんだけど自 // 前で以下のマクロを必要に応じて宣言してやってくだされ。 // // ・AVAILABLE_MEMBER_TEMPLATES ( tricklib_AVAILABLE_MEMBER_TEMPLATES ) // コンパイラがメンバーテンプレートに対応していることを示します。 // // 各種コンパイラの仕様識別に関して詳しい情報をお持ちの方は道化師 // ( mailto:wraith@trickpalace.net )まで連絡をくれると助かります。 // Borland ... # if defined(__BORLANDC__) # if 540 <= __BORLANDC__ # define tricklib_AVAILABLE_MEMBER_TEMPLATES # endif # endif // CodeWarrior ... # if defined(__MWERKS__) # if 0x2401 <= __MWERKS__ // 6.2以上 # define tricklib_AVAILABLE_MEMBER_TEMPLATES # endif # endif // Microsoft ... # if defined(_MSC_VER) # endif // gcc/g++ ... # if defined(__GNUC__) # if 2 < __GNUC__ || 2 == __GNUC__ && 8 <= __GNUC_MINOR__ # define tricklib_AVAILABLE_MEMBER_TEMPLATES # endif # endif // Digital Mars ... # if defined(__DMC__) # endif // 省略形の宣言 ... # ifdef USING_TRICKLIB # ifdef tricklib_AVAILABLE_MEMBER_TEMPLATES # define AVAILABLE_MEMBER_TEMPLATES # endif # endif // // ■ 標準的(常識的)なマクロ // // ■ 配列の要素数を取得するマクロ // // 用例: // int x[10]; // for(int i = 0; i < ARRAY_SIZE(x); ++i) { // x[i] = i; // } // # ifdef USING_TRICKLIB # define ARRAY_SIZE tricklib_ARRAY_SIZE # endif # define tricklib_ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0])) // ■ 配列の末尾(の次要素)を取得するマクロ // // 用例: // int x[10]; // for(int *i = x; i < ARRAY_END(x); ++i) { // *i = 0; // } // # ifdef USING_TRICKLIB # define ARRAY_END tricklib_ARRAY_END # endif # define tricklib_ARRAY_END(X) (X +tricklib_ARRAY_SIZE(X)) // ■ for 文での変数スコープ標準化マクロ // // 用例: // int i = x; // std_for(int i = 0; i < size; ++i) { // ... // } // # ifdef USING_TRICKLIB # define std_for tricklib_std_for # endif # define tricklib_std_for if(0) ; else for // // ■ コメント関連マクロ // // ■ インラインでのコメントを記述するためのマクロ // // cf. http://www.tietew.jp/cppll/archive/818 // # ifdef USING_TRICKLIB # define memo tricklib_memo # endif # define tricklib_memo(x) // ■ ダミー引数であることの明示をするためのマクロ // // cf. http://www.tietew.jp/cppll/archive/818 // # ifdef USING_TRICKLIB # define no_use tricklib_no_use # endif # define tricklib_no_use // // ■ キャスト関連関数テンプレート // // ■ const 属性を除去する関数テンプレート // // cf. http://www.tietew.jp/cppll/archive/38 // template inline T & disconst (const T &Value) { return const_cast(Value); } // ■ 指定された変数/オブジェクトと同じ型にキャストする関数テンプレート // // キャスト時に型名を指定したくない時のための関数テンプレー // トです。この関数テンプレートは第二引数で指定された変数を // 第一引数で指定した変数と同じ型にキャストします。 // // 用例: // return *sync_cast(this, NULL); // // cf. http://www.tietew.jp/cppll/archive/266 // template inline T sync_cast(const T &, const U x) { return (T)x; } // // ■ 汎用テンプレート // // ■ 類似クラステンプレート // // ターゲットの型をラップするだけのクラステンプレートです。 // 幅広く応用の利ききますが、主には、一時オブジェクトの作成 // 及び一時オブジェクトの左辺値化、各種都合により同じ型を別 // の型として認識させるためなどに利用できます。ターゲットの // 型があらかじめポインタだと分かっている場合は demi の代わ // りに nullable/not_null を使用することをお薦めします。 // // cf. http://www.tietew.jp/cppll/archive/67 // cf. http://www.tietew.jp/cppll/archive/167 // template class demi { public: T value; demi() {} demi(const T &X) :value(X) {} operator T& () { return value; } operator const T& () const { return value; } T * operator & () { return &value; } const T * operator & () const { return &value; } T & operator () () { return value; } const T & operator () () const { return value; } }; // // ■ ポインタ関連テンプレート // // ■ NULL 許容ポインタテンプレート // // cf. http://www.tietew.jp/cppll/archive/819 // template class nullable :public demi { public: nullable(T *x = NULL) :demi(x) {} bool operator ! () const { return !value; } nullable& operator ++ () { ++value; return *this; } const T* operator ++ (int) { return value++; } nullable& operator -- () { --value; return *this; } const T* operator -- (int) { return value--; } const T* operator + (int index) const { return value +index; } nullable& operator += (int index) { value += index; return *this; } const T* operator - (int index) const { return value -index; } nullable& operator -= (int index) { value -= index; return *this; } T& operator*() { return *value; } const T& operator*() const { return *value; } T* operator->() { return value; } const T* operator->() const { return value; } T& operator[](const int index) { return value[index]; } const T& operator[](const int index) const { return value[index]; } bool is_null() const { return NULL == value; } }; // ■ NULL 拒否ポインタテンプレート // // cf. http://www.tietew.jp/cppll/archive/819 // cf. http://www.tietew.jp/cppll/archive/820 // template class not_null :public nullable { public: not_null(T *x) :nullable(x) { assert(!is_null()); } }; // // ■ catapillar FI // // ■ 最大値取得ギミック // // 用例: // int x = max_in(A)(B)(C)(D)(E); // // cf. http://www.tietew.jp/cppll/archive/533 // cf. http://www.tietew.jp/cppll/archive/534 // template class max_in_core :public demi { public: max_in_core(const T &x) :demi(x) {} max_in_core& operator()(const T& x) { if (value < x) { value = x; } return *this; } }; template inline max_in_core max_in(const T&x) { return x; } // ■ 最小値取得ギミック // // 用例: // int x = min_in(A)(B)(C)(D)(E); // template class min_in_core :public demi { public: min_in_core(const T &x) :demi(x) {} min_in_core& operator()(const T& x) { if (x < value) { value = x; } return *this; } }; template inline min_in_core min_in(const T&x) { return x; } // ■ 要素数取得ギミック // // 用例: // int x = number_in(A)(B)(C)(D)(E); // template class number_in_core :public demi { public: number_in_core(const T &) :demi(1) {} number_in_core& operator()(const T &) { ++value; return *this; } }; template inline number_in_core number_in(const T&x) { return x; } // ■ 合計値取得ギミック // // 用例: // int x = total_in(A)(B)(C)(D)(E); // template class total_in_core :public demi { public: total_in_core(const T &x) :demi(x) {} total_in_core& operator()(const T& x) { value += x; return *this; } }; template inline total_in_core total_in(const T&x) { return x; } // ■ 平均値取得ギミック // // 用例: // double x = average_in(A)(B)(C)(D)(E); // template class average_in_core { number_in_core number; total_in_core total; public: average_in_core(const T &x) :number(x), total(x) {} average_in_core& operator()(const T& x) { number(x), total(x); return *this; } # ifdef tricklib_AVAILABLE_MEMBER_TEMPLATES template operator U () const { return ((U)total.value)/((U)number.value); } # else operator const T () const { return total.value/((T)number.value); } # endif const T operator () () const { return operator const T(); } }; template inline average_in_core average_in(const T&x) { return x; } // ■ コンテナへの代入ギミック // // 用例: // vector vec_int; // mighty_append(vec_int)(A)(B)(C)(D)(E); // int x[] = { 1, 2, 3, 4, 5 }; // mighty_append(vec_int)(x, ARRAY_END(x)); // template class mighty_append_core { C &container; public: typedef typename C::value_type value_type; typedef typename C::iterator iterator; mighty_append_core(C &x) :container(x) {} C& operator()() { return container; } mighty_append_core& operator()(const value_type& x) { container.insert(container.end(), x); return *this; } # ifdef tricklib_AVAILABLE_MEMBER_TEMPLATES template mighty_append_core& operator()(InputIterator begin, InputIterator end) { for(InputIterator i = begin; i != end; ++i) { container.insert(container.end(), *i); } return *this; } # else mighty_append_core& operator()(const value_type *begin, const value_type *end) { for(const value_type *i = begin; i != end; ++i) { container.insert(container.end(), *i); } return *this; } # endif operator C& () { return container; } operator iterator () { return container.end(); } }; template inline mighty_append_core mighty_append(T&x) { return x; } // // ■ その他もろもろ... // // ■ 条件式簡略化ギミック // // このギミックを用いれば 'A <= B && B < C && C != D' といっ // た条件式が 'expression(A <= B < C != D)' のように簡潔に記 // 述できます。 // // ただし、上記 A, B, C, D が関数などの場合、 'A <= B && B < // C && C != D' とは異なり先行する条件判定結果に関わらず評価 // (実行)されてしまいます。 // // また、非常に残念なことですがこのギミックには大きな欠陥が // あります。それは <, <=, >, >= より先に ==, != が使用でき // ないことです。演算子の結合順位が ==, != と <, <=, >, >= // では異なるため... // // if (expression(A != B <= C < D)) { // ← これはダメ。(x_x) // ... // } // // ...のように ==, != が <, <=, >, >= より先に使用されると // このギミックは破綻してしまいます。 // // cf. http://www.tietew.jp/cppll/archive/327 // # ifdef USING_TRICKLIB # define expression tricklib_expression # endif # define tricklib_expression(XXX) \ ((tricklib::expression_start() << XXX).result) class expression_start {}; template class expression_joint { public: bool result; const T &value; expression_joint(bool _result, const T &_value) :result(_result), value(_value) {} }; template inline expression_joint operator<<(const expression_start &, const T &value) { return expression_joint(true, value); } template inline expression_joint operator==(expression_joint joint, const U &value) { return expression_joint( joint.result && joint.value == value, value); } template inline expression_joint operator!=(expression_joint joint, const U &value) { return expression_joint( joint.result && joint.value != value, value); } template inline expression_joint operator<(expression_joint joint, const U &value) { return expression_joint( joint.result && joint.value < value, value); } template inline expression_joint operator<=(expression_joint joint, const U &value) { return expression_joint( joint.result && joint.value <= value, value); } template inline expression_joint operator>(expression_joint joint, const U &value) { return expression_joint( joint.result && joint.value > value, value); } template inline expression_joint operator>=(expression_joint joint, const U &value) { return expression_joint( joint.result && joint.value >= value, value); } } // tricklib #endif // __TrickLibrary_TIPS_H__ /****************************************************************************** □■□■ Wraith the Trickster □■□■ ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ ******************************************************************************/