//////////////////////////////////////////////////////////////////////////// // // multivalue.h マルチヴァリュー // // programmed by Robert (2002/06/09) // #ifndef ___MULTIVALUE_H__200206090146__INCLUDED___ #define ___MULTIVALUE_H__200206090146__INCLUDED___ /* マルチヴァリューを扱うためのマクロとテンプレートです クラスを含める場合、コピーコンストラクタが何度も呼ばれるので、 コピーコンストラクタが複雑なクラスは避けた方が無難です 普通の値であれば inline 展開により十分高速なコードが生成されます 使用例) Type2(int, int) hoge() { return Value2(1, 2); } hoge() >> a >> b; // >> 演算子で取り出します cout << a << ":" << b << endl; // 1:2 と出力されます Type2(const char*, bool) sage() { // 文字列リテラルは暗黙では char* になります return Value2("sage", true); } if((sage() >> s).Get()) // Get を使うと変数に保存せずに使えます cout << s << endl; Type3(int, int, int) age(Value3(7, 8, 9)); // 普通の変数としても使えます age >> a >> b; // 別に3つの値全てを取り出す必要はありません cout << a << ":" << b << endl; age = Value3(5, 6, 7); age.Skip() >> b; // 2番目の値だけを取得します cout << b << endl; age = RomanticAgeRuyo(); // 戻り値の型は Type3(int, int, int) です age >> a >> b >> c; cout << a << b << c << endl; */ /* 複数の値を保持するためのクラスその1 1つの値を保持して、>> 演算子を使って値を取り出します 通常、Type 系マクロと Value 系関数テンプレートを通じて構築します >> 演算子の引数で必然的に t_value1& という型を使うので、 t_value1 は参照型にはできません */ template class CMultivalue1 { private: t_value1 m_value1; // 保持しておく値 public: // 値を保持するコンストラクタ explicit CMultivalue1(t_value1& value1) : m_value1(value1) { } // 何もしないコンストラクタ CMultivalue1() { } // 値を取り出します void operator>>(t_value1& value1) const { value1 = m_value1; } // value1 を取得します t_value1 Get() const { return m_value1; } }; /* 複数の値を保持するためのクラスその2 2つの値を保持して、>> 演算子を使って値を取り出します 通常、Type 系マクロと Value 系関数テンプレートを通じて構築します >> 演算子の引数で必然的に t_value1& という型を使うので、 t_value1 は参照型にはできません t_value2 には CMultivalue1/2 型を与えます このあたりは Type 系マクロと Value 系関数テンプレートを使えば 勝手にやってくれます */ template class CMultivalue2 { private: t_value1 m_value1; // 保持しておく値1 t_value2 m_value2; // 保持しておく値2(通例 CMultivalue1/2 型) public: // 値を保持するコンストラクタ CMultivalue2(t_value1& value1, t_value2& value2) : m_value1(value1), m_value2(value2) { } // 何もしないコンストラクタ CMultivalue2() { } // 値を取り出します const t_value2& operator>>(t_value1& value1) const { value1 = m_value1; return m_value2; } t_value2& operator>>(t_value1& value1) { value1 = m_value1; return m_value2; } // value1 を取得します t_value1 Get() const { return m_value1; } // 値を1つ飛ばします const t_value2& Skip() const { return m_value2; } t_value2& Skip() { return m_value2; } }; /* Type 系マクロ マルチヴァリュー型を指定する時に使います t_value1& などを使うことがあるという仕様上、 参照型は指定できません */ // 1つの値用のマルチヴァリュー型 #define Type1(t_value1) \ CMultivalue1 // 2つの値用のマルチヴァリュー型 #define Type2(t_value1, t_value2) \ CMultivalue2 // ← ) と > の間の空白を消してはいけない! // 3つの値用のマルチヴァリュー型 #define Type3(t_value1, t_value2, t_value3) \ CMultivalue2 // ← ) と > の間の空白を消してはいけない! // 4つの値用のマルチヴァリュー型 #define Type4(t_value1, t_value2, t_value3, t_value4) \ CMultivalue2 // ← ) と > の間の空白を消してはいけない! // 5つの値用のマルチヴァリュー型 #define Type5(t_value1, t_value2, t_value3, t_value4, t_value5) \ CMultivalue2 // ← ) と > の間の空白を消してはいけない! // 6つの値用のマルチヴァリュー型 #define Type6(t_value1, t_value2, t_value3, t_value4, t_value5, t_value6) \ CMultivalue2 // ← ) と > の間の空白を消してはいけない! // これ以上は必要になったときに各自増やしてください /* Value 系関数テンプレート マルチヴァリューを生成する時に使います 参照に対してリテラルを渡した際に     ・・ .NET ではテンポラリ変数を作って渡してくれなくなってるので 引数は値渡しにしておきます */ // 1つの値用のマルチ(?)ヴァリューオブジェクトを返します template inline Type1(t_value1) Value1(t_value1 value1) { return Type1(t_value1)(value1); } // 2つの値用のマルチヴァリューオブジェクトを返します template inline Type2(t_value1, t_value2) Value2(t_value1 value1, t_value2 value2) { Type1(t_value2) multi(Value1(value2)); return Type2(t_value1, t_value2)(value1, multi); } // 3つの値用のマルチヴァリューオブジェクトを返します template inline Type3(t_value1, t_value2, t_value3) Value3(t_value1 value1, t_value2 value2, t_value3 value3) { Type2(t_value2, t_value3) multi(Value2(value2, value3)); return Type3(t_value1, t_value2, t_value3)(value1, multi); } // 4つの値用のマルチヴァリューオブジェクトを返します template inline Type4(t_value1, t_value2, t_value3, t_value4) Value4(t_value1 value1, t_value2 value2, t_value3 value3, t_value4 value4) { Type3(t_value2, t_value3, t_value4) multi(Value3(value2, value3, value4)); return Type4(t_value1, t_value2, t_value3, t_value4)(value1, multi); } // 5つの値用のマルチヴァリューオブジェクトを返します template inline Type5(t_value1, t_value2, t_value3, t_value4, t_value5) Value5(t_value1 value1, t_value2 value2, t_value3 value3, t_value4 value4, t_value5 value5) { Type4(t_value2, t_value3, t_value4, t_value5) multi(Value4(value2, value3, value4, value5)); return Type5(t_value1, t_value2, t_value3, t_value4, t_value5)(value1, multi); } // 6つの値用のマルチヴァリューオブジェクトを返します template inline Type6(t_value1, t_value2, t_value3, t_value4, t_value5, t_value6) Value6(t_value1 value1, t_value2 value2, t_value3 value3, t_value4 value4, t_value5 value5, t_value6 value6) { Type5(t_value2, t_value3, t_value4, t_value5, t_value6) multi(Value5(value2, value3, value4, value5, value6)); return Type6(t_value1, t_value2, t_value3, t_value4, t_value5, t_value6)(value1, multi); } // これ以上は必要になったときに各自増やしてください #endif // #ifndef ___MULTIVALUE_H__200206090146__INCLUDED___