OSDN Git Service

sublexer.cppに定義されていたlexerの再定義が完了したため、削除。
[simplecms/utakata.git] / lib / bool_compareble.h
1 // safe boolイディオムの実装をサポートするCRTPを提供します
2 // 以下のように利用されることを想定しています。
3 // class Test : private bool_compareble<Test> {
4 //   bool operator!() const {return true;}
5 // };
6 // Test t;
7 // if (t) {std::cout << "true" << std::endl;}
8 // if (!t) {}
9 // if (t != false) {std::cout << "OK" << std::endl;}
10 //
11 // このファイルで提供されるbool_comparebleを利用した場合、bool_compareble
12 // を継承したクラス間においては、operator==、operator!==の利用を
13 // 行うことができなくなります。
14 #ifndef _UATKATA_LIB_BOOL_COMPAREBLE_H_
15 #define _UTAKATA_LIB_BOOL_COMPAREBLE_H_
16
17 namespace akebono {
18 namespace crtp {
19
20 // コンパイルエラーを発生させるためのヘルパ構造体です。
21 // それぞれ、this_type_support_comparisonsは、コンパイル可能である
22 // 場合に利用され、this_type_does_not_support_comparisonsは、
23 // コンパイル不能である場合に利用されます。
24 struct bool_compareble_helper {
25   void this_type_support_comparisons() const {}
26  private:
27   bool this_type_does_not_support_comparisons() const {}
28 };
29
30 // 継承先のクラスに対して、自動的にsafe-boolイディオムを適用するための
31 // テンプレートです。
32 // class hoge : private bool_compareble<hoge>のように利用します。
33 // 継承先のクラスでは、必ずoperator!が定義されていなければなりません。
34 template<class T>
35 class bool_compareble {
36
37   // コンパイル時の確認のために利用されます。
38   typedef void (bool_compareble<T>::*unspecified_bool)() const;
39
40   // unspecified_bool型の有効である関数ポインタを返します。
41   unspecified_bool bool_value_() {
42     reinterpret_cast<unspecified_bool>(
43         &bool_compareble_helper().this_type_support_comparisons);
44   }
45
46  public:
47
48   // void()型への型変換時に実行される関数ですが、この関数は実行される
49   // ことは無く、実行可能であるかどうかを判別するための関数
50   // となります。
51   // operator!が存在しない場合、コンパイルエラーが発生します。
52   operator unspecified_bool() const {
53     return !(static_cast<const T*>(this)->operator!()) ? bool_value_() : 0;
54   }
55
56   // boolとの比較の際、ADPでのみLookupが行われるように定義される
57   // friendなoperatorです。
58   // ただし、この場合x == 1のような表現が許容されます。
59   friend bool operator==(const T& lhs, bool rhs) const {
60     return static_cast<bool>(lhs) == rhs;
61   }
62
63   friend bool operator==(bool lhs, const T& rhs) const {
64     return lhs == static_cast<bool>(rhs);
65   }
66
67   friend bool operator!=(const T& lhs, bool rhs) const {
68     return static_cast<bool>(lhs) == rhs;
69   }
70
71   friend bool operator!=(bool lhs, const T& rhs) const {
72     return lhs == static_cast<bool>(rhs);
73   }
74
75   // それぞれ、bool_compareble同士の比較を許可しないための
76   // オペレータオーバーロードとなります。
77   // すべてのbool_comparebleを対象とするため、テンプレート引数は
78   // 指定されません。
79   // 元の同士に対して、比較が必要である場合、適宜operator==を定義する
80   // 必要があります。
81   friend bool operator==(const bool_compareble& lhs,
82                          const bool_compareble& lhs) {
83     return bool_compareble_helper().this_type_does_not_support_comparisons();
84   }
85
86   friend bool operator!=(const bool_compareble& lhs,
87                          const bool_compareble& lhs) {
88     return bool_compareble_helper().this_type_does_not_support_comparisons();
89   }
90
91  protected:
92
93   // 外部からの明示的な生成は許可されません。
94   bool_compareble() {}
95   ~bool_compareble() {}
96 };
97
98 } // end of namespace crtp
99 } // end of namespace akebono
100
101 #endif /* _UTAKATA_LIB_BOOL_COMPAREBLE_H_ */