OSDN Git Service

first commit.
[gintenlib/gintenlib.git] / gintenlib / bool_comparable.hpp
1 #ifndef GINTENLIB_INCLUDED_BOOL_COMPARABLE_HPP_
2 #define GINTENLIB_INCLUDED_BOOL_COMPARABLE_HPP_
3
4 /*
5   bool_comparable : safe_bool¥¤¥Ç¥£¥ª¥àÄó¶¡
6   
7   Àë¸À¡§
8     template<typename Derived>
9     class bool_comparable
10     {
11      public:
12       // safe_bool ËÜÂÎ
13       operator unspecified_bool_type() const;
14       // ÇÉÀ¸¤·¤¿¥¯¥é¥¹¤Î¦¤Ç operator! ¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¡¢
15       // ÇÉÀ¸¤·¤¿¥¯¥é¥¹¤Î boolean_test() ¥á¥ó¥Ð´Ø¿ô¤¬¤¢¤ì¤Ð¤½¤ÎÈÝÄê¤òÊÖ¤¹¡£
16       // operator!() ¤â boolean_test() ¤â¤Ê¤±¤ì¤Ð¡¢¥¨¥é¡¼
17       bool operator!() const;
18     
19       // bool ¤È¤ÎÈæ³Ó¡£ int ¤Î¤È¤­¤ÏÈ¿±þ¤·¤Ê¤¤¤è¤¦¤Ë¤Ê¤Ã¤Æ¤Þ¤¹
20       friend bool operator==( const bool_comparable& lhs, bool rhs );
21       friend bool operator==( bool lhs, const bool_comparable& rhs );
22       friend bool operator!=( const bool_comparable& lhs, bool rhs );
23       friend bool operator!=( bool lhs, const bool_comparable& rhs );
24     
25      protected:
26       bool_comparable() {}
27       ~bool_comparable() {}
28     
29     };  // class bool_comparable<Derived>
30     
31         
32     // Â¾¡¢¸Æ¤Ó½Ð¤µ¤ì¤ë¤È¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼¤Ë¤Ê¤ë operator== ¤È operator!= ¤¬Àë¸À¤µ¤ì¤Æ¤¤¤Þ¤¹
33
34   µ¡Ç½¡§
35     boost::operators ¤ß¤¿¤¤¤Ê´¶¤¸¤Ë¡¢´Êñ¤Ë safe_bool ¥¤¥Ç¥£¥ª¥à¤ò¼Â¸½¤·¤Þ¤¹¡£
36     »ÈÍÑË¡¤Ï¡¢bool_comparable ¤Î¥Æ¥ó¥×¥ì¡¼¥È°ú¿ô¤ËÀ½ºî¤¹¤ë¥¯¥é¥¹¤Î̾Á°¤òÆþ¤ì¤Æ public ·Ñ¾µ¡£
37     ¤½¤·¤ÆÀ½ºî¤¹¤ë¥¯¥é¥¹¤Ë¡¢
38       bool operator!() const;
39     ´Ø¿ô¤«¡¢¤¢¤ë¤¤¤Ï
40       bool boolean_test() const;
41     ´Ø¿ô¤Î¤É¤Á¤é¤«¤òÄêµÁ¤¹¤ì¤Ð£Ï£Ë¤Ç¤¹¡ÊξÊý¤¢¤ë¾ì¹ç¤Ï operator!() ¤¬Í¥À褵¤ì¤Þ¤¹¡Ë¡£
42   
43   »ÈÍÑË¡ : 
44     // Îã¤È¤·¤Æ boost::optional Åª¤Ê²¿¤«¤òºî¤ê¤Þ¤·¤ç¤¦
45     #include <boost/scoped_ptr.hpp>
46     
47     template<typename T>
48     class my_optional
49       : public gintenlib::bool_comparable< my_optional<T> > // ¤³¤Î¤è¤¦¤Ë»È¤¦
50     {
51       // ËÜÂÎÉôʬ¤Ï¤Ê¤ó¤éµ¤¤Ë¤»¤º½ñ¤¤¤Æ¤è¤¤
52      public:
53       typedef  T  value_type;
54       
55       typedef       T&       reference;
56       typedef const T& const_reference;
57       
58       my_optional() : p() {}
59       my_optional( const T& x ) : p( new T(x) ) {}
60       
61       reference        operator*()       { return *p; }
62       const_reference  operator*() const { return *p; }
63       
64       // operator!() ¤ò³Î¼Â¤Ë¼ÂÁõ¤¹¤ë¤³¤È¤ò˺¤ì¤Ê¤±¤ì¤Ð¡£
65       bool operator!() const
66       {
67         return !p;
68       }
69       // ¤³¤ì¤Ë¤è¤ê¡¢boolÈæ³Ó¤â½ÐÍè¤ë¤è¤¦¤Ë¤Ê¤ë
70       
71       // ¤Á¤Ê¤ß¤Ë operator!() ¤¸¤ã¤Ê¤¯¤Æ
72       // bool boolean_test() const { return p.get(); }
73       // ¤³¤ì¤Ç¤â¤¤¤¤¡Ê¤½¤Î¾ì¹ç¡¢operator! ¤Ï¼«Æ°ÄêµÁ¡Ë
74       
75       // ¤½¤Î¤Û¤«¡¢¥³¥Ô¡¼¥³¥ó¥¹¥È¥é¥¯¥¿¤È¤«ÂåÆþ±é»»»Ò¤È¤«¤ÏÌÌÅݤÀ¤«¤é¾Êά
76       
77      private:
78       // ÌÌÅݤʥݥ¤¥ó¥¿´ÉÍý¤È¤«¤·¤¿¤¯¤Ê¤¤¤Î¤Ç scoped_ptr ¤ò»È¤¦
79       boost::scoped_ptr<T> p;
80       
81     };
82     
83     int main()
84     {
85       my_optional<int> a, b(1), c(0);
86       
87       // if ¤Î¾ò·ïÉô¤È¤·¤Æ
88       if( a )
89       {
90         assert( !"a is empty." );
91       }
92       
93       // && ¤ä || ¤ÈÁȤ߹ç¤ï¤»¤Æ
94       assert( b && c );
95       
96       // ¥¼¥í¤È¤ÎÈæ³Ó
97       assert( a == 0 && b != 0 && c != 0 );
98       // assert( b == 1 );  // 1 ¤È¤ÏÈæ³Ó¤Ç¤­¤Ê¤¤
99       
100       // bool ÃͤȤÎÈæ³Ó
101       assert( a == false && b == true && c == true );
102       // static_cast
103       assert( static_cast<bool>(b) == static_cast<bool>(c) );
104       // assert( a != b ); // ¥³¥ì¤Ï¥À¥á¡Ê¤â¤· b ¤È c ¤òÈæ³Ó¤·¤¿¤é¡©¡Ë
105
106   Ãí°Õ»ö¹à¡§
107     ¡¦boost::enable_if ¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡£¸Å¤¤¥³¥ó¥Ñ¥¤¥é¤Ç¤ÏÆ°¤­¤Þ¤»¤ó¡£
108     ¡¦¤½¤ì¤¬·ù¤Ê¤é GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF ¥Þ¥¯¥í¤òÄêµÁ¤¹¤ì¤Ð£Ï£Ë¤Ç¤¹¡£
109     ¡¦¤¿¤À¤·¡¢¤½¤Î¾ì¹ç¡¢¾å¤ÎÎã¤Ç¤Î¡Öb == 1¡×Ū¤Êɽ¸½¤¬¥³¥ó¥Ñ¥¤¥ëÄ̤äƤ·¤Þ¤¤¤Þ¤¹¡£
110     
111     ¡¦¡Ö a == b ¡×¤Î¤è¤¦¤Ê¡¢ÇÉÀ¸Àè¤Î¥¯¥é¥¹Æ±»Î¤Ç¤ÎÈæ³Ó¤Ï¡¢¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼¤Ë¤Ê¤ê¤Þ¤¹¡£
112     ¡¦¤Ç¤¹¤¬¡¢ÅöÁ³¡¢ÇÉÀ¸Àè¤Ç operator== ¤òÄêµÁ¤·¤Æ¤ª¤±¤Ð¡¢¤­¤Á¤ó¤ÈÈæ³Ó¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
113     ¡¦¤¿¤À¤·¡¢ÇÉÀ¸Àè¤Î¥¯¥é¥¹¤¬¡Ö 0 ¤«¤é°ÅÌÛÊÑ´¹²Äǽ¡×¤Ç¤¢¤ê¡Öoperator==¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡×¾ì¹ç¤Ï¡¢
114       ¡Ö x == 0 ¡×¤Î¤è¤¦¤ÊÈæ³Ó¤¬¡¢¥¼¥í¤È¤ÎÈæ³Ó¤Ë¸Â¤ê¤Ç¤¹¤¬¡¢½ÐÍè¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹:
115         struct convertible_from_int
116           : gintenlib::bool_comparable<convertible_from_int>,
117             private boost::equality_comparable<convertible_from_int>
118         {
119           int value;
120           convertible_from_int( int x = 0 ) : value(x) {} // int ¤«¤é°ÅÌÛÊÑ´¹¤Ç¤­¤ë¤È¡¦¡¦¡¦
121           
122           bool operator!() const { return value == 0; }
123           
124           // operator== ¤Ë¤è¤ëÈæ³Ó¤¬½ÐÍè¤ë¾ì¹ç
125           friend bool operator==( const convertible_from_int& lhs, const convertible_from_int& rhs )
126           {
127             return lhs.value == rhs.value;
128           }
129          
130         };  
131         
132         int main()
133         {
134           convertible_from_int x, y = 2;
135           assert( !x ); // ¤³¤¦¤¤¤¦¤Î¤ÏÉáÄ̤˽ÐÍè¤ë¤¬
136           assert( y );
137           assert( x == false );
138           assert( y == true );
139           
140           // assert( x == 0 ); // ¥³¥ì¤¬¼Â¹Ô¤Ç¤­¤Ê¤¤¡ÊÛ£Ëæ¤Ë¤Ê¤Ã¤Æ¤·¤Þ¤¦¡Ë
141           // assert( y != 0 ); // ÅöÁ³¤³¤ì¤â¥À¥á
142           
143           assert( y == 2 ); // ¤Ç¤â¥³¥ì¤Ï£Ï£Ë
144           assert( x != 1 ); // ¥³¥ì¤â£Ï£Ë
145         }
146        
147     ¡¦¤½¤Î¾ì¹ç¤Ï int ¤È¤ÎÈæ³Ó¤òÊ̸ÄÄêµÁ¤·¤Æ¤ä¤ì¤Ð£Ï£Ë¤Ç¤¹¡§
148         struct convertible_from_int
149           : gintenlib::bool_comparable<convertible_from_int>,
150             private boost::equality_comparable<convertible_from_int>,
151             private boost::equality_comparable<convertible_from_int, int>
152         {
153           int value;
154           convertible_from_int( int x = 0 ) : value(x) {} // int ¤«¤é°ÅÌÛÊÑ´¹¤Ç¤­¤ë¾ì¹ç¤Ç¤â
155           
156           bool boolean_test() const { return value; } // boolean_test ¤ò»È¤Ã¤Æ¤ß¤ë¡£
157           
158           friend bool operator==( const piyo& lhs, const piyo& rhs )
159           {
160             return lhs.value == rhs.value;
161           }
162           // int ¤È¤ÎÈæ³Ó¤òÌÀ¼¨Åª¤ËÄêµÁ¤µ¤¨¤¹¤ì¤Ð
163           friend bool operator==( const convertible_from_int& lhs, int rhs )
164           {
165             return lhs.value == rhs;
166           }
167          
168         };
169         
170         int main()
171         {
172           convertible_from_int x, y(2)
173           assert( x == 0 ); // £Ï£Ë
174           assert( y != 0 );
175         }
176     
177 */
178
179 #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
180   #include "enable_if.hpp"
181   #include <boost/type_traits/is_same.hpp>
182 #endif
183
184 namespace gintenlib
185 {
186   // ¥Ø¥ë¥Ñ¹½Â¤ÂÎ
187   struct bool_comparable_helper
188   {
189     // operator bool_type() ¤ÎÌá¤êÃͤȤ·¤Æ»È¤ï¤ì¤ëÃÍ
190     void bool_value() const {}
191     
192    private:
193     // ¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼¤òµ¯¤³¤¹¤¿¤á¤Î private ´Ø¿ô
194     bool this_type_does_not_support_comparisons_();
195   
196   };
197   
198   // ËÜÂÎ
199   template<typename Derived>
200   class bool_comparable
201   {
202     // safe-bool ¤Ë»È¤¦·¿¡Ê¥á¥ó¥Ð´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¡Ë
203     typedef void (bool_comparable::*bool_type)() const;
204     
205     // ÇÉÀ¸¤·¤¿¥¯¥é¥¹¤òÆÀ¤ë´Ø¿ô
206     const Derived& derived() const { return *static_cast<const Derived*>(this); }
207           Derived& derived()       { return *static_cast<      Derived*>(this); }
208     
209     // Â¾¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ç¤â derived ¤Ï»È¤¤¤¿¤¤¤¼
210     template<typename U> friend class bool_comparable;
211     
212    public:
213     // ËÜÂê
214     operator bool_type() const
215     {
216       return bool_test_() ? bool_value_() : 0;
217       // bool_test_, bool_value_ ¤Ï¸å¤ÇÄêµÁ¤¹¤ë
218     }
219   
220     // bool ¤È¤ÎÈæ³Ó
221     
222   #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
223     
224     // enable_if ¤Ç bool ¤ÈÈæ³Ó¤¹¤ë»þ¤À¤±Í­¸ú¤Ë¤¹¤ë¤³¤È¤Ç¡¢x == 1 ¤Î¤è¤¦¤ÊÈæ³Ó¤ò̵Îϲ½¤¹¤ë
225     // todo: g++ °Ê³°¤Î¥³¥ó¥Ñ¥¤¥é¤Ç¤ÎÆ°ºî¥Á¥§¥Ã¥¯
226     
227     // ¼ÂÁõ
228     template<typename U>
229     friend typename enable_if<boost::is_same<U, bool>, bool>::type
230       operator==( const Derived& lhs, U rhs )
231     {
232       return static_cast<bool>(lhs) == rhs;
233     }
234     template<typename U>
235     friend typename enable_if<boost::is_same<U, bool>, bool>::type
236       operator==( U lhs, const Derived& rhs )
237     {
238       return lhs == static_cast<bool>(rhs);
239     }
240     template<typename U>
241     friend typename enable_if<boost::is_same<U, bool>, bool>::type
242       operator!=( const Derived& lhs, U rhs )
243     {
244       return static_cast<bool>(lhs) != rhs;
245     }
246     template<typename U>
247     friend typename enable_if<boost::is_same<U, bool>, bool>::type
248       operator!=( U lhs, const Derived& rhs )
249     {
250       return lhs != static_cast<bool>(rhs);
251     }
252     
253   #else   // #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
254     
255     // °ì±þ enable_if ¤ò»È¤ï¤Ê¤¤ÈǤâÍÑ°Õ
256     // ¤³¤Î¾ì¹ç¡¢ x == 1 ¤Î¤è¤¦¤Êɽ¸½¤¬Ä̤äƤ·¤Þ¤¦¤¬»ÅÊý¤Ê¤¤¤Í
257     friend bool operator==( const Derived& lhs, bool rhs )
258     {
259       return static_cast<bool>(lhs) == rhs;
260     }
261     friend bool operator==( bool lhs, const Derived& rhs )
262     {
263       return lhs == static_cast<bool>(rhs);
264     }
265     friend bool operator!=( const Derived& lhs, bool rhs )
266     {
267       return static_cast<bool>(lhs) != rhs;
268     }
269     friend bool operator!=( bool lhs, const Derived& rhs )
270     {
271       return lhs != static_cast<bool>(rhs);
272     }
273     
274   #endif  // #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
275   
276    private:
277     // ¼ÂÁõÊä½õ
278     // bool_type ¤È¤·¤ÆÊÖ¤¹ÃÍ
279     static bool_type bool_value_()
280     {
281       // ´Ø¿ô¤ò̵Â̤˺î¤é¤»¤Ê¤¤¹©Éס£¤É¤¦¤» bool_type ¤ÎÃͤϻȤï¤Ê¤¤¤·
282       return reinterpret_cast<bool_type>( &bool_comparable_helper::bool_value );
283     }
284     
285     // ¥Æ¥¹¥È´Ø¿ô
286     // ¤Þ¤º Derived::operator!() ¤ò¸«¤Ë¹Ô¤¯
287     bool bool_test_() const
288     {
289       return !( !derived() );
290     }
291     
292    public:
293     // Derived Â¦¤Ç operator!() ¤¬ÄêµÁ¤µ¤ì¤Æ̵¤¤¤Ê¤é
294     // Derived::boolean_test() ´Ø¿ô¤¬¤Ê¤¤¤«Ãµ¤·¡¢Ìµ¤±¤ì¤Ð¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼
295     bool operator!() const
296     {
297       return !( derived().boolean_test() );
298     }
299     // friend ´Ø¿ôÈÇ¡£Â¸ºß¤¹¤ë°ÕÌ£¤ÏÆäË̵¤¤¡£
300     friend bool boolean_test( const bool_comparable& x )
301     {
302       return x.bool_test_();
303     }
304     
305     // Èæ³Ó¤Ï¥¨¥é¡¼¤Ë¤Ê¤ë¡Ê Derived Â¦¤ÇÆÃÊ̤ËÄêµÁ¤¹¤ì¤Ð£Ï£Ë¡Ë
306     
307     // ÅùÃÍÈæ³Ó
308     friend bool operator==( const bool_comparable& lhs, const bool_comparable& rhs )
309     {
310       return bool_comparable_helper().this_type_does_not_support_comparisons_();
311     }
312     // ÉÔÅùÃÍÈæ³Ó
313     friend bool operator!=( const bool_comparable& lhs, const bool_comparable& rhs )
314     {
315       return bool_comparable_helper().this_type_does_not_support_comparisons_();
316     }
317   
318    protected:
319     // ÇÉÀ¸¥¯¥é¥¹°Ê³°¤«¤é¤Î¹½Ã۶ػß
320      bool_comparable() {}
321     ~bool_comparable() {}
322     
323   };  // class bool_comparable<Derived>
324
325 } // namespace gintenlib
326
327 #endif  // #ifndef GINTENLIB_INCLUDED_BOOL_COMPARABLE_HPP_