1 // safe boolイディオムの実装をサポートするCRTPを提供します
2 // 以下のように利用されることを想定しています。
3 // class Test : private bool_compareble<Test> {
4 // bool operator!() const {return true;}
7 // if (t) {std::cout << "true" << std::endl;}
9 // if (t != false) {std::cout << "OK" << std::endl;}
11 // このファイルで提供されるbool_comparebleを利用した場合、bool_compareble
12 // を継承したクラス間においては、operator==、operator!==の利用を
14 #ifndef _UATKATA_LIB_BOOL_COMPAREBLE_H_
15 #define _UTAKATA_LIB_BOOL_COMPAREBLE_H_
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 {}
27 bool this_type_does_not_support_comparisons() const {}
30 // 継承先のクラスに対して、自動的にsafe-boolイディオムを適用するための
32 // class hoge : private bool_compareble<hoge>のように利用します。
33 // 継承先のクラスでは、必ずoperator!が定義されていなければなりません。
35 class bool_compareble {
37 // コンパイル時の確認のために利用されます。
38 typedef void (bool_compareble<T>::*unspecified_bool)() const;
40 // unspecified_bool型の有効である関数ポインタを返します。
41 unspecified_bool bool_value_() {
42 reinterpret_cast<unspecified_bool>(
43 &bool_compareble_helper().this_type_support_comparisons);
48 // void()型への型変換時に実行される関数ですが、この関数は実行される
49 // ことは無く、実行可能であるかどうかを判別するための関数
51 // operator!が存在しない場合、コンパイルエラーが発生します。
52 operator unspecified_bool() const {
53 return !(static_cast<const T*>(this)->operator!()) ? bool_value_() : 0;
56 // boolとの比較の際、ADPでのみLookupが行われるように定義される
58 // ただし、この場合x == 1のような表現が許容されます。
59 friend bool operator==(const T& lhs, bool rhs) const {
60 return static_cast<bool>(lhs) == rhs;
63 friend bool operator==(bool lhs, const T& rhs) const {
64 return lhs == static_cast<bool>(rhs);
67 friend bool operator!=(const T& lhs, bool rhs) const {
68 return static_cast<bool>(lhs) == rhs;
71 friend bool operator!=(bool lhs, const T& rhs) const {
72 return lhs == static_cast<bool>(rhs);
75 // それぞれ、bool_compareble同士の比較を許可しないための
77 // すべてのbool_comparebleを対象とするため、テンプレート引数は
79 // 元の同士に対して、比較が必要である場合、適宜operator==を定義する
81 friend bool operator==(const bool_compareble& lhs,
82 const bool_compareble& lhs) {
83 return bool_compareble_helper().this_type_does_not_support_comparisons();
86 friend bool operator!=(const bool_compareble& lhs,
87 const bool_compareble& lhs) {
88 return bool_compareble_helper().this_type_does_not_support_comparisons();
93 // 外部からの明示的な生成は許可されません。
98 } // end of namespace crtp
99 } // end of namespace akebono
101 #endif /* _UTAKATA_LIB_BOOL_COMPAREBLE_H_ */