YSTest: operators.hpp 源文件

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
57 YB_OP_TEMPLATE_HEADER2(less_than_comparable2) : _tBase
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
67 YB_OP_TEMPLATE_HEADER1(less_than_comparable1) : _tBase
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
75 YB_OP_TEMPLATE_HEADER2(equality_comparable2) : _tBase
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
82 YB_OP_TEMPLATE_HEADER1(equality_comparable1) : _tBase
83 {
84 YB_OP_COMPARE1(!=, !bool(x == y), _type)
85 };
86
87
88 YB_OP_TEMPLATE_HEADER2(equivalent2) : _tBase
89 {
90 YB_OP_COMPARE2(!=, !bool(x < y) && !bool(x > y), _type, _type2)
91 };
92
93 YB_OP_TEMPLATE_HEADER1(equivalent1) : _tBase
94 {
95 YB_OP_COMPARE1(!=, !bool(x < y) && !bool(y < x), _type)
96 };
97
98
99 YB_OP_TEMPLATE_HEADER2(partially_ordered2) : _tBase
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
109 YB_OP_TEMPLATE_HEADER1(partially_ordered1) : _tBase
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, -)
149 YB_OP_NON_COMMUTATIVE(dividable, /)
150 YB_OP_NON_COMMUTATIVE(modable, %)
151 YB_OP_COMMUTATIVE(xorable, ^)
152 YB_OP_COMMUTATIVE(andable, &)
153 YB_OP_COMMUTATIVE(orable, |)
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
174 YB_OP_TEMPLATE_HEADER1(incrementable) : _tBase
175 {
176 friend _type
177 operator++(_type& x, int)
178 {
179 _type t(x);
180
181 ++x;
182 return t;
183 }
184 };
185
186 YB_OP_TEMPLATE_HEADER1(decrementable) : _tBase
187 {
188 friend _type
189 operator--(_type& x, int)
190 {
191 _type t(x);
192
193 ++x;
194 return t;
195 }
196 };
197
198 YB_OP_TEMPLATE_HEADER1(dereferenceable) : _tBase
199 {
200 auto
201 operator->() const -> decltype(&*std::declval<const _type&>())
202 {
203 return &*static_cast<const _type&>(*this);
204 }
205 };
206
207 YB_OP_TEMPLATE_HEADER2(indexable) : _tBase
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
218 YB_OP_TEMPLATE_HEADER2(totally_ordered2)
219 : less_than_comparable2<_type, _type2,
220 equality_comparable2<_type, _type2, _tBase>
221 >
222 {};
223
224 YB_OP_TEMPLATE_HEADER1(totally_ordered1)
225 : less_than_comparable1<_type, equality_comparable1<_type, _tBase>>
226 {};
227
228
229 YB_OP_TEMPLATE_HEADER2(additive2)
230 : addable2<_type, _type2, subtractable2<_type, _type2, _tBase>>
231 {};
232
233 YB_OP_TEMPLATE_HEADER1(additive1)
234 : addable1<_type, subtractable1<_type, _tBase>>
235 {};
236
237
238 YB_OP_TEMPLATE_HEADER2(multiplicative2)
239 : multipliable2<_type, _type2, dividable2<_type, _type2, _tBase>>
240 {};
241
242 YB_OP_TEMPLATE_HEADER1(multiplicative1)
243 : multipliable1<_type, dividable1<_type, _tBase>>
244 {};
245
246
247 YB_OP_TEMPLATE_HEADER2(integer_multiplicative2)
248 : multiplicative2<_type, _type2, modable2<_type, _type2, _tBase>>
249 {};
250
251 YB_OP_TEMPLATE_HEADER1(integer_multiplicative1)
252 : multiplicative1<_type, modable1<_type, _tBase>>
253 {};
254
255
256 YB_OP_TEMPLATE_HEADER2(arithmetic2)
257 : additive2<_type, _type2, multiplicative2<_type, _type2, _tBase>>
258 {};
259
260 YB_OP_TEMPLATE_HEADER1(arithmetic1)
261 : additive1<_type, multiplicative1<_type, _tBase>>
262 {};
263
264
265 YB_OP_TEMPLATE_HEADER2(integer_arithmetic2)
266 : additive2<_type, _type2,
267 integer_multiplicative2<_type, _type2, _tBase>
268 >
269 {};
270
271 YB_OP_TEMPLATE_HEADER1(integer_arithmetic1)
272 : additive1<_type, integer_multiplicative1<_type, _tBase>>
273 {};
274
275
276 YB_OP_TEMPLATE_HEADER2(bitwise2)
277 : xorable2<_type, _type2, andable2<_type, _type2,
278 orable2<_type, _type2, _tBase>>
279 >
280 {};
281
282 YB_OP_TEMPLATE_HEADER1(bitwise1)
283 : xorable1<_type, andable1<_type, orable1<_type, _tBase>>>
284 {};
285
286
287 YB_OP_TEMPLATE_HEADER1(unit_steppable)
288 : incrementable<_type, decrementable<_type, _tBase>>
289 {};
290
291
292 YB_OP_TEMPLATE_HEADER2(shiftable2)
293 : left_shiftable2<_type, _type2,
294 right_shiftable2<_type, _type2, _tBase>
295 >
296 {};
297
298 YB_OP_TEMPLATE_HEADER1(shiftable1)
299 : left_shiftable1<_type, right_shiftable1<_type, _tBase>>
300 {};
301
302
303 YB_OP_TEMPLATE_HEADER2(ring_operators2)
304 : additive2<_type, _type2, subtractable2_left<_type, _type2,
305 multipliable2<_type, _type2, _tBase>>
306 >
307 {};
308
309 YB_OP_TEMPLATE_HEADER1(ring_operators1)
310 : additive1<_type, multipliable1<_type, _tBase>>
311 {};
312
313
314 YB_OP_TEMPLATE_HEADER2(ordered_ring_operators2)
315 : ring_operators2<_type, _type2,
316 totally_ordered2<_type, _type2, _tBase>
317 >
318 {};
319
320 YB_OP_TEMPLATE_HEADER1(ordered_ring_operators1)
321 : ring_operators1<_type, totally_ordered1<_type, _tBase>>
322 {};
323
324
325 YB_OP_TEMPLATE_HEADER2(field_operators2)
326 : ring_operators2<_type, _type2, dividable2<_type, _type2,
327 dividable2_left<_type, _type2, _tBase>>
328 >
329 {};
330
331 YB_OP_TEMPLATE_HEADER1(field_operators1)
332 : ring_operators1<_type, dividable1<_type, _tBase>>
333 {};
334
335
336 YB_OP_TEMPLATE_HEADER2(ordered_field_operators2)
337 : field_operators2<_type, _type2,
338 totally_ordered2<_type, _type2, _tBase>
339 >
340 {};
341
342 YB_OP_TEMPLATE_HEADER1(ordered_field_operators1)
343 : field_operators1<_type, totally_ordered1<_type, _tBase>>
344 {};
345
346
347 YB_OP_TEMPLATE_HEADER2(euclidian_ring_operators2)
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
355 YB_OP_TEMPLATE_HEADER1(euclidian_ring_operators1)
356 : ring_operators1<_type, dividable1<_type, modable1<_type, _tBase>>>
357 {};
358
359
360 YB_OP_TEMPLATE_HEADER2(ordered_euclidian_ring_operators2)
361 : totally_ordered2<_type, _type2,
362 euclidian_ring_operators2<_type, _type2, _tBase>
363 >
364 {};
365
366 YB_OP_TEMPLATE_HEADER1(ordered_euclidian_ring_operators1)
367 : totally_ordered1<_type, euclidian_ring_operators1<_type, _tBase>>
368 {};
369
370
371 YB_OP_TEMPLATE_HEADER2(euclidean_ring_operators2)
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
379 YB_OP_TEMPLATE_HEADER1(euclidean_ring_operators1)
380 : ring_operators1<_type, dividable1<_type, modable1<_type, _tBase>>>
381 {};
382
383
384 YB_OP_TEMPLATE_HEADER2(ordered_euclidean_ring_operators2)
385 : totally_ordered2<_type, _type2,
386 euclidean_ring_operators2<_type, _type2, _tBase>
387 >
388 {};
389
390 YB_OP_TEMPLATE_HEADER1(ordered_euclidean_ring_operators1)
391 : totally_ordered1<_type, euclidean_ring_operators1<_type, _tBase>>
392 {};
393
394
395 YB_OP_TEMPLATE_HEADER1(input_iteratable)
396 : equality_comparable1<_type, incrementable<_type,
397 dereferenceable<_type, _tBase>>
398 >
399 {};
400
401
402 YB_OP_TEMPLATE_HEADER1(output_iteratable)
403 : incrementable<_type, _tBase>
404 {};
405
406
407 YB_OP_TEMPLATE_HEADER1(forward_iteratable)
408 : input_iteratable<_type, _tBase>
409 {};
410
411
412 YB_OP_TEMPLATE_HEADER1(bidirectional_iteratable)
413 : forward_iteratable<_type, decrementable<_type, _tBase>>
414 {};
415
416
417 YB_OP_TEMPLATE_HEADER2(random_access_iteratable)
418 : bidirectional_iteratable<_type, less_than_comparable1<_type,
419 additive2<_type, _type2, indexable<_type, _type2, _tBase>>>
420 >
421 {};
422
423 } // namespace details;
424
425
430 namespace operators
431 {
432
433 template<class>
434 struct is_chained_base
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
483 YB_OP_CHAIN(less_than_comparable)
484 YB_OP_CHAIN(equality_comparable)
485 YB_OP_CHAIN(multipliable)
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
503 YB_OP_CHAIN(left_shiftable)
504 YB_OP_CHAIN(right_shiftable)
505 YB_OP_CHAIN(equivalent)
506 YB_OP_CHAIN(partially_ordered)
507
508 YB_OP_CHAIN(totally_ordered)
509 YB_OP_CHAIN(additive)
510 YB_OP_CHAIN(multiplicative)
511 YB_OP_CHAIN(integer_multiplicative)
512 YB_OP_CHAIN(arithmetic)
513 YB_OP_CHAIN(integer_arithmetic)
514 YB_OP_CHAIN(bitwise)
515 YB_OP_CHAIN1(unit_steppable)
516 YB_OP_CHAIN(shiftable)
517 YB_OP_CHAIN(ring_operators)
518 YB_OP_CHAIN(ordered_ring_operators)
519 YB_OP_CHAIN(field_operators)
520 YB_OP_CHAIN(ordered_field_operators)
521 YB_OP_CHAIN(euclidian_ring_operators)
522 YB_OP_CHAIN(ordered_euclidian_ring_operators)
523 YB_OP_CHAIN(euclidean_ring_operators)
524 YB_OP_CHAIN(ordered_euclidean_ring_operators)
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