YSTest  PreAlpha_b400_20130424
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
operators.hpp
浏览该文件的文档.
1 /*
2  Copyright (C) by Franksoft 2011 - 2012.
3 
4  This file is part of the YSLib project, and may only be used,
5  modified, and distributed under the terms of the YSLib project
6  license, LICENSE.TXT. By continuing to use, modify, or distribute
7  this file you indicate that you have read the license and
8  understand and accept it fully.
9 */
10 
28 #ifndef YB_INC_YSTDEX_OPERATORS_HPP_
29 #define YB_INC_YSTDEX_OPERATORS_HPP_ 1
30 
31 #include "../ydef.h"
32 
33 namespace ystdex
34 {
35 
36 #define YB_OP_FRIEND(_op, _tRet, _expr, ...) \
37  friend yconstfn _tRet operator _op (__VA_ARGS__) {return (_expr);}
38 #define YB_OP_TEMPLATE_HEADER2(_name) \
39  template<class _type, class _type2, class _tBase = empty_base<_type>> \
40  struct _name
41 #define YB_OP_TEMPLATE_HEADER1(_name) \
42  template<class _type, class _tBase = empty_base<_type>> \
43  struct _name
44 
45 
46 namespace details
47 {
48 
49 #define YB_OP_COMPARE2(_op, _expr, _param_type, _param_type2) \
50  YB_OP_FRIEND(_op, bool, _expr, const _param_type& x, \
51  const _param_type2& y)
52 #define YB_OP_COMPARE1(_op, _expr, _param_type) \
53  YB_OP_FRIEND(_op, bool, _expr, const _param_type& x, \
54  const _param_type& y)
55 
56 
58 {
59  YB_OP_COMPARE2(<=, !bool(x > y), _type, _type2)
60  YB_OP_COMPARE2(>=, !bool(x < y), _type, _type2)
61  YB_OP_COMPARE2(>, y < x, _type2, _type)
62  YB_OP_COMPARE2(<, y > x, _type2, _type)
63  YB_OP_COMPARE2(<=, !bool(y < x), _type2, _type)
64  YB_OP_COMPARE2(>=, !bool(y > x), _type2, _type)
65 };
66 
68 {
69  YB_OP_COMPARE1(>, y < x, _type)
70  YB_OP_COMPARE1(<=, !bool(y < x), _type)
71  YB_OP_COMPARE1(>=, !bool(x < y), _type)
72 };
73 
74 
76 {
77  YB_OP_COMPARE2(==, x == y, _type2, _type)
78  YB_OP_COMPARE2(!=, !bool(x == y), _type2, _type)
79  YB_OP_COMPARE2(!=, !bool(y == x), _type, _type2)
80 };
81 
83 {
84  YB_OP_COMPARE1(!=, !bool(x == y), _type)
85 };
86 
87 
89 {
90  YB_OP_COMPARE2(!=, !bool(x < y) && !bool(x > y), _type, _type2)
91 };
92 
94 {
95  YB_OP_COMPARE1(!=, !bool(x < y) && !bool(y < x), _type)
96 };
97 
98 
100 {
101  YB_OP_COMPARE2(<=, bool(x < y) || bool(x == y), _type, _type2)
102  YB_OP_COMPARE2(>=, bool(x > y) || bool(x == y), _type, _type2)
103  YB_OP_COMPARE2(>, y < x, _type2, _type)
104  YB_OP_COMPARE2(<, y > x, _type2, _type)
105  YB_OP_COMPARE2(<=, bool(y > x) || bool(y == x), _type2, _type)
106  YB_OP_COMPARE2(>=, bool(y < x) || bool(y == x), _type2, _type)
107 };
108 
110 {
111  YB_OP_COMPARE1(>, y < x, _type)
112  YB_OP_COMPARE1(<=, bool(x < y) || bool(x == y), _type)
113  YB_OP_COMPARE1(>=, bool(y < x) || bool(x == y), _type)
114 };
115 
116 #undef YB_OP_COMPARE2
117 #undef YB_OP_COMPARE1
118 
119 
120 #define YB_OP_COMMUTATIVE(_name, _op) \
121  YB_OP_TEMPLATE_HEADER2(_name##2) : _tBase \
122  { \
123  YB_OP_FRIEND(_op, _type, x _op##= y, _type x, const _type2& y) \
124  YB_OP_FRIEND(_op, _type, y _op##= x, const _type2& y, _type x) \
125  }; \
126  YB_OP_TEMPLATE_HEADER1(_name##1) : _tBase \
127  { \
128  YB_OP_FRIEND(_op, _type, x _op##= y, _type x, const _type& y) \
129  };
130 
131 #define YB_OP_NON_COMMUTATIVE(_name, _op) \
132  YB_OP_TEMPLATE_HEADER2(_name##2) : _tBase \
133  { \
134  YB_OP_FRIEND(_op, _type, x _op##= y, _type x, const _type2& y) \
135  }; \
136  YB_OP_TEMPLATE_HEADER2(_name##2##_##left) : _tBase \
137  { \
138  YB_OP_FRIEND(_op, _type, _type(x) _op##= y, const _type2& x, \
139  const _type& y) \
140  }; \
141  YB_OP_TEMPLATE_HEADER1(_name##1) : _tBase \
142  { \
143  YB_OP_FRIEND(_op, _type, x _op##= y, _type x, const _type& y) \
144  };
145 
146 YB_OP_COMMUTATIVE(multipliable, *)
147 YB_OP_COMMUTATIVE(addable, +)
148 YB_OP_NON_COMMUTATIVE(subtractable, -)
151 YB_OP_COMMUTATIVE(xorable, ^)
152 YB_OP_COMMUTATIVE(andable, &)
154 
155 #undef YB_OP_NON_COMMUTATIVE
156 #undef YB_OP_COMMUTATIVE
157 
158 
159 #define YB_OP_BINARY(_name, _op) \
160  YB_OP_TEMPLATE_HEADER2(_name##2) : _tBase \
161  { \
162  YB_OP_FRIEND(_op, _type, x _op##= y, _type x, const _type2& y) \
163  }; \
164  YB_OP_TEMPLATE_HEADER1(_name##1) : _tBase \
165  { \
166  YB_OP_FRIEND(_op, _type, x _op##= y, _type x, const _type& y) \
167  };
168 
169  YB_OP_BINARY(left_shiftable, <<)
170  YB_OP_BINARY(right_shiftable, >>)
171 
172 #undef YB_OP_BINARY
173 
175 {
176  friend _type
177  operator++(_type& x, int)
178  {
179  _type t(x);
180 
181  ++x;
182  return t;
183  }
184 };
185 
187 {
188  friend _type
189  operator--(_type& x, int)
190  {
191  _type t(x);
192 
193  ++x;
194  return t;
195  }
196 };
197 
199 {
200  auto
201  operator->() const -> decltype(&*std::declval<const _type&>())
202  {
203  return &*static_cast<const _type&>(*this);
204  }
205 };
206 
208 {
209  auto
210  operator[](_type2 n) const
211  -> decltype(*(std::declval<const _type&>() + n))
212  {
213  return *(static_cast<const _type&>(*this) + n);
214  }
215 };
216 
217 
219  : less_than_comparable2<_type, _type2,
220  equality_comparable2<_type, _type2, _tBase>
221  >
222 {};
223 
225  : less_than_comparable1<_type, equality_comparable1<_type, _tBase>>
226 {};
227 
228 
230  : addable2<_type, _type2, subtractable2<_type, _type2, _tBase>>
231 {};
232 
234  : addable1<_type, subtractable1<_type, _tBase>>
235 {};
236 
237 
239  : multipliable2<_type, _type2, dividable2<_type, _type2, _tBase>>
240 {};
241 
243  : multipliable1<_type, dividable1<_type, _tBase>>
244 {};
245 
246 
248  : multiplicative2<_type, _type2, modable2<_type, _type2, _tBase>>
249 {};
250 
252  : multiplicative1<_type, modable1<_type, _tBase>>
253 {};
254 
255 
257  : additive2<_type, _type2, multiplicative2<_type, _type2, _tBase>>
258 {};
259 
261  : additive1<_type, multiplicative1<_type, _tBase>>
262 {};
263 
264 
266  : additive2<_type, _type2,
267  integer_multiplicative2<_type, _type2, _tBase>
268  >
269 {};
270 
272  : additive1<_type, integer_multiplicative1<_type, _tBase>>
273 {};
274 
275 
277  : xorable2<_type, _type2, andable2<_type, _type2,
278  orable2<_type, _type2, _tBase>>
279  >
280 {};
281 
283  : xorable1<_type, andable1<_type, orable1<_type, _tBase>>>
284 {};
285 
286 
288  : incrementable<_type, decrementable<_type, _tBase>>
289 {};
290 
291 
293  : left_shiftable2<_type, _type2,
294  right_shiftable2<_type, _type2, _tBase>
295  >
296 {};
297 
299  : left_shiftable1<_type, right_shiftable1<_type, _tBase>>
300 {};
301 
302 
304  : additive2<_type, _type2, subtractable2_left<_type, _type2,
305  multipliable2<_type, _type2, _tBase>>
306  >
307 {};
308 
310  : additive1<_type, multipliable1<_type, _tBase>>
311 {};
312 
313 
315  : ring_operators2<_type, _type2,
316  totally_ordered2<_type, _type2, _tBase>
317  >
318 {};
319 
321  : ring_operators1<_type, totally_ordered1<_type, _tBase>>
322 {};
323 
324 
326  : ring_operators2<_type, _type2, dividable2<_type, _type2,
327  dividable2_left<_type, _type2, _tBase>>
328  >
329 {};
330 
332  : ring_operators1<_type, dividable1<_type, _tBase>>
333 {};
334 
335 
337  : field_operators2<_type, _type2,
338  totally_ordered2<_type, _type2, _tBase>
339  >
340 {};
341 
343  : field_operators1<_type, totally_ordered1<_type, _tBase>>
344 {};
345 
346 
348  : ring_operators2<_type, _type2, dividable2<_type, _type2,
349  dividable2_left<_type, _type2, modable2<_type, _type2,
350  modable2_left<_type, _type2, _tBase>>>
351  >
352  >
353 {};
354 
356  : ring_operators1<_type, dividable1<_type, modable1<_type, _tBase>>>
357 {};
358 
359 
361  : totally_ordered2<_type, _type2,
362  euclidian_ring_operators2<_type, _type2, _tBase>
363  >
364 {};
365 
367  : totally_ordered1<_type, euclidian_ring_operators1<_type, _tBase>>
368 {};
369 
370 
372  : ring_operators2<_type, _type2, dividable2<_type, _type2,
373  dividable2_left<_type, _type2, modable2<_type, _type2,
374  modable2_left<_type, _type2, _tBase>>>
375  >
376  >
377 {};
378 
380  : ring_operators1<_type, dividable1<_type, modable1<_type, _tBase>>>
381 {};
382 
383 
385  : totally_ordered2<_type, _type2,
386  euclidean_ring_operators2<_type, _type2, _tBase>
387  >
388 {};
389 
391  : totally_ordered1<_type, euclidean_ring_operators1<_type, _tBase>>
392 {};
393 
394 
396  : equality_comparable1<_type, incrementable<_type,
397  dereferenceable<_type, _tBase>>
398  >
399 {};
400 
401 
403  : incrementable<_type, _tBase>
404 {};
405 
406 
408  : input_iteratable<_type, _tBase>
409 {};
410 
411 
413  : forward_iteratable<_type, decrementable<_type, _tBase>>
414 {};
415 
416 
419  additive2<_type, _type2, indexable<_type, _type2, _tBase>>>
420  >
421 {};
422 
423 } // namespace details;
424 
425 
430 namespace operators
431 {
432 
433  template<class>
435  : public false_type
436  {};
437 
438 
439 # define YB_OP_CHAIN2(_name) \
440  using ystdex::details::_name; \
441  template<class _type, class _type2, class _tBase> \
442  struct is_chained_base<_name<_type, _type2, _tBase>> \
443  : public true_type \
444  {};
445 
446 # define YB_OP_CHAIN1(_name) \
447  using ystdex::details::_name; \
448  template<class _type, class _tBase> \
449  struct is_chained_base<_name<_type, _tBase>> \
450  : public true_type \
451  {};
452 
453 #define YB_OP_CHAIN(_name) \
454  using ystdex::details::_name##2; \
455  template<class _type, class _type2 = _type, \
456  class _tBase = empty_base<_type>, \
457  bool _v = is_chained_base<_type2>::value \
458  > \
459  struct _name \
460  : _name##2<_type, _type2, _tBase> \
461  {}; \
462  \
463  using ystdex::details::_name##1; \
464  template<class _type, class _type2, class _tBase> \
465  struct _name<_type, _type2, _tBase, true> \
466  : _name##1<_type, _type2> \
467  {}; \
468  \
469  template <class _type, class _tBase> \
470  struct _name<_type, _type, _tBase, false> \
471  : _name##1<_type, _tBase> \
472  {}; \
473  \
474  template<class _type, class _type2, class _tBase, bool _v> \
475  struct is_chained_base<_name<_type, _type2, _tBase, _v>> \
476  : public true_type \
477  {}; \
478  \
479  YB_OP_CHAIN2(_name##2) \
480  YB_OP_CHAIN1(_name##1)
481 
482 
486 YB_OP_CHAIN(addable)
487 YB_OP_CHAIN(subtractable)
488 YB_OP_CHAIN2(subtractable2_left)
489 YB_OP_CHAIN(dividable)
490 YB_OP_CHAIN2(dividable2_left)
491 YB_OP_CHAIN(modable)
492 YB_OP_CHAIN2(modable2_left)
493 YB_OP_CHAIN(xorable)
494 YB_OP_CHAIN(andable)
495 YB_OP_CHAIN(orable)
496 
497 YB_OP_CHAIN1(incrementable)
498 YB_OP_CHAIN1(decrementable)
499 
500 YB_OP_CHAIN1(dereferenceable)
501 YB_OP_CHAIN2(indexable)
502 
504 YB_OP_CHAIN(right_shiftable)
507 
515 YB_OP_CHAIN1(unit_steppable)
525 YB_OP_CHAIN1(input_iteratable)
526 YB_OP_CHAIN1(output_iteratable)
527 YB_OP_CHAIN1(forward_iteratable)
528 YB_OP_CHAIN1(bidirectional_iteratable)
529 YB_OP_CHAIN2(random_access_iteratable)
530 
531 #undef YB_OP_CHAIN2
532 #undef YB_OP_CHAIN1
533 #undef YB_OP_CHAIN
534 
535 } // namespace operators;
536 
537 #undef YB_OP_TEMPLATE_HEADER1
538 #undef YB_OP_TEMPLATE_HEADER2
539 #undef YB_OP_FRIEND
540 
541 } // namespace ystdex;
542 
543 #endif
544