1 | // |
2 | // (C) Copyright Jeremy Siek 2000. |
3 | // Copyright 2002 The Trustees of Indiana University. |
4 | // |
5 | // Distributed under the Boost Software License, Version 1.0. (See |
6 | // accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | // |
9 | // Revision History: |
10 | // 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) |
11 | // 02 April 2001: Removed limits header altogether. (Jeremy Siek) |
12 | // 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock) |
13 | // |
14 | |
15 | // See http://www.boost.org/libs/concept_check for documentation. |
16 | |
17 | #ifndef BOOST_CONCEPT_CHECKS_HPP |
18 | # define BOOST_CONCEPT_CHECKS_HPP |
19 | |
20 | # include <boost/concept/assert.hpp> |
21 | |
22 | # include <iterator> |
23 | # include <boost/type_traits/conversion_traits.hpp> |
24 | # include <utility> |
25 | # include <boost/type_traits/is_same.hpp> |
26 | # include <boost/type_traits/is_void.hpp> |
27 | # include <boost/mpl/assert.hpp> |
28 | # include <boost/mpl/bool.hpp> |
29 | # include <boost/detail/workaround.hpp> |
30 | |
31 | # include <boost/concept/usage.hpp> |
32 | # include <boost/concept/detail/concept_def.hpp> |
33 | |
34 | #if (defined _MSC_VER) |
35 | # pragma warning( push ) |
36 | # pragma warning( disable : 4510 ) // default constructor could not be generated |
37 | # pragma warning( disable : 4610 ) // object 'class' can never be instantiated - user-defined constructor required |
38 | #endif |
39 | |
40 | namespace boost |
41 | { |
42 | |
43 | // |
44 | // Backward compatibility |
45 | // |
46 | |
47 | template <class Model> |
48 | inline void function_requires(Model* = 0) |
49 | { |
50 | BOOST_CONCEPT_ASSERT((Model)); |
51 | } |
52 | template <class T> inline void ignore_unused_variable_warning(T const&) {} |
53 | |
54 | # define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ |
55 | BOOST_CONCEPT_ASSERT((ns::concept<type_var>)) |
56 | |
57 | # define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ |
58 | BOOST_CONCEPT_ASSERT((ns::concept<type_var1,type_var2>)) |
59 | |
60 | # define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ |
61 | BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3>)) |
62 | |
63 | # define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ |
64 | BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3,tv4>)) |
65 | |
66 | |
67 | // |
68 | // Begin concept definitions |
69 | // |
70 | BOOST_concept(Integer, (T)) |
71 | { |
72 | BOOST_CONCEPT_USAGE(Integer) |
73 | { |
74 | x.error_type_must_be_an_integer_type(); |
75 | } |
76 | private: |
77 | T x; |
78 | }; |
79 | |
80 | template <> struct Integer<char> {}; |
81 | template <> struct Integer<signed char> {}; |
82 | template <> struct Integer<unsigned char> {}; |
83 | template <> struct Integer<short> {}; |
84 | template <> struct Integer<unsigned short> {}; |
85 | template <> struct Integer<int> {}; |
86 | template <> struct Integer<unsigned int> {}; |
87 | template <> struct Integer<long> {}; |
88 | template <> struct Integer<unsigned long> {}; |
89 | # if defined(BOOST_HAS_LONG_LONG) |
90 | template <> struct Integer< ::boost::long_long_type> {}; |
91 | template <> struct Integer< ::boost::ulong_long_type> {}; |
92 | # elif defined(BOOST_HAS_MS_INT64) |
93 | template <> struct Integer<__int64> {}; |
94 | template <> struct Integer<unsigned __int64> {}; |
95 | # endif |
96 | |
97 | BOOST_concept(SignedInteger,(T)) { |
98 | BOOST_CONCEPT_USAGE(SignedInteger) { |
99 | x.error_type_must_be_a_signed_integer_type(); |
100 | } |
101 | private: |
102 | T x; |
103 | }; |
104 | template <> struct SignedInteger<signed char> { }; |
105 | template <> struct SignedInteger<short> {}; |
106 | template <> struct SignedInteger<int> {}; |
107 | template <> struct SignedInteger<long> {}; |
108 | # if defined(BOOST_HAS_LONG_LONG) |
109 | template <> struct SignedInteger< ::boost::long_long_type> {}; |
110 | # elif defined(BOOST_HAS_MS_INT64) |
111 | template <> struct SignedInteger<__int64> {}; |
112 | # endif |
113 | |
114 | BOOST_concept(UnsignedInteger,(T)) { |
115 | BOOST_CONCEPT_USAGE(UnsignedInteger) { |
116 | x.error_type_must_be_an_unsigned_integer_type(); |
117 | } |
118 | private: |
119 | T x; |
120 | }; |
121 | |
122 | template <> struct UnsignedInteger<unsigned char> {}; |
123 | template <> struct UnsignedInteger<unsigned short> {}; |
124 | template <> struct UnsignedInteger<unsigned int> {}; |
125 | template <> struct UnsignedInteger<unsigned long> {}; |
126 | # if defined(BOOST_HAS_LONG_LONG) |
127 | template <> struct UnsignedInteger< ::boost::ulong_long_type> {}; |
128 | # elif defined(BOOST_HAS_MS_INT64) |
129 | template <> struct UnsignedInteger<unsigned __int64> {}; |
130 | # endif |
131 | |
132 | //=========================================================================== |
133 | // Basic Concepts |
134 | |
135 | BOOST_concept(DefaultConstructible,(TT)) |
136 | { |
137 | BOOST_CONCEPT_USAGE(DefaultConstructible) { |
138 | TT a; // require default constructor |
139 | ignore_unused_variable_warning(a); |
140 | } |
141 | }; |
142 | |
143 | BOOST_concept(Assignable,(TT)) |
144 | { |
145 | BOOST_CONCEPT_USAGE(Assignable) { |
146 | #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL |
147 | a = b; // require assignment operator |
148 | #endif |
149 | const_constraints(b); |
150 | } |
151 | private: |
152 | void const_constraints(const TT& x) { |
153 | #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL |
154 | a = x; // const required for argument to assignment |
155 | #else |
156 | ignore_unused_variable_warning(x); |
157 | #endif |
158 | } |
159 | private: |
160 | TT a; |
161 | TT b; |
162 | }; |
163 | |
164 | |
165 | BOOST_concept(CopyConstructible,(TT)) |
166 | { |
167 | BOOST_CONCEPT_USAGE(CopyConstructible) { |
168 | TT a(b); // require copy constructor |
169 | TT* ptr = &a; // require address of operator |
170 | const_constraints(a); |
171 | ignore_unused_variable_warning(ptr); |
172 | } |
173 | private: |
174 | void const_constraints(const TT& a) { |
175 | TT c(a); // require const copy constructor |
176 | const TT* ptr = &a; // require const address of operator |
177 | ignore_unused_variable_warning(c); |
178 | ignore_unused_variable_warning(ptr); |
179 | } |
180 | TT b; |
181 | }; |
182 | |
183 | // The SGI STL version of Assignable requires copy constructor and operator= |
184 | BOOST_concept(SGIAssignable,(TT)) |
185 | { |
186 | BOOST_CONCEPT_USAGE(SGIAssignable) { |
187 | TT c(a); |
188 | #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL |
189 | a = b; // require assignment operator |
190 | #endif |
191 | const_constraints(b); |
192 | ignore_unused_variable_warning(c); |
193 | } |
194 | private: |
195 | void const_constraints(const TT& x) { |
196 | TT c(x); |
197 | #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL |
198 | a = x; // const required for argument to assignment |
199 | #endif |
200 | ignore_unused_variable_warning(c); |
201 | } |
202 | TT a; |
203 | TT b; |
204 | }; |
205 | |
206 | BOOST_concept(Convertible,(X)(Y)) |
207 | { |
208 | BOOST_CONCEPT_USAGE(Convertible) { |
209 | Y y = x; |
210 | ignore_unused_variable_warning(y); |
211 | } |
212 | private: |
213 | X x; |
214 | }; |
215 | |
216 | // The C++ standard requirements for many concepts talk about return |
217 | // types that must be "convertible to bool". The problem with this |
218 | // requirement is that it leaves the door open for evil proxies that |
219 | // define things like operator|| with strange return types. Two |
220 | // possible solutions are: |
221 | // 1) require the return type to be exactly bool |
222 | // 2) stay with convertible to bool, and also |
223 | // specify stuff about all the logical operators. |
224 | // For now we just test for convertible to bool. |
225 | template <class TT> |
226 | void require_boolean_expr(const TT& t) { |
227 | bool x = t; |
228 | ignore_unused_variable_warning(x); |
229 | } |
230 | |
231 | BOOST_concept(EqualityComparable,(TT)) |
232 | { |
233 | BOOST_CONCEPT_USAGE(EqualityComparable) { |
234 | require_boolean_expr(a == b); |
235 | require_boolean_expr(a != b); |
236 | } |
237 | private: |
238 | TT a, b; |
239 | }; |
240 | |
241 | BOOST_concept(LessThanComparable,(TT)) |
242 | { |
243 | BOOST_CONCEPT_USAGE(LessThanComparable) { |
244 | require_boolean_expr(a < b); |
245 | } |
246 | private: |
247 | TT a, b; |
248 | }; |
249 | |
250 | // This is equivalent to SGI STL's LessThanComparable. |
251 | BOOST_concept(Comparable,(TT)) |
252 | { |
253 | BOOST_CONCEPT_USAGE(Comparable) { |
254 | require_boolean_expr(a < b); |
255 | require_boolean_expr(a > b); |
256 | require_boolean_expr(a <= b); |
257 | require_boolean_expr(a >= b); |
258 | } |
259 | private: |
260 | TT a, b; |
261 | }; |
262 | |
263 | #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ |
264 | BOOST_concept(NAME, (First)(Second)) \ |
265 | { \ |
266 | BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ |
267 | private: \ |
268 | bool constraints_() { return a OP b; } \ |
269 | First a; \ |
270 | Second b; \ |
271 | } |
272 | |
273 | #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ |
274 | BOOST_concept(NAME, (Ret)(First)(Second)) \ |
275 | { \ |
276 | BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ |
277 | private: \ |
278 | Ret constraints_() { return a OP b; } \ |
279 | First a; \ |
280 | Second b; \ |
281 | } |
282 | |
283 | BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp); |
284 | BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp); |
285 | BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOp); |
286 | BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOp); |
287 | BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOp); |
288 | BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOp); |
289 | |
290 | BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOp); |
291 | BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOp); |
292 | BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOp); |
293 | BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOp); |
294 | BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOp); |
295 | |
296 | //=========================================================================== |
297 | // Function Object Concepts |
298 | |
299 | BOOST_concept(Generator,(Func)(Return)) |
300 | { |
301 | BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); } |
302 | |
303 | private: |
304 | void test(boost::mpl::false_) |
305 | { |
306 | // Do we really want a reference here? |
307 | const Return& r = f(); |
308 | ignore_unused_variable_warning(r); |
309 | } |
310 | |
311 | void test(boost::mpl::true_) |
312 | { |
313 | f(); |
314 | } |
315 | |
316 | Func f; |
317 | }; |
318 | |
319 | BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) |
320 | { |
321 | BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); } |
322 | |
323 | private: |
324 | void test(boost::mpl::false_) |
325 | { |
326 | f(arg); // "priming the pump" this way keeps msvc6 happy (ICE) |
327 | Return r = f(arg); |
328 | ignore_unused_variable_warning(r); |
329 | } |
330 | |
331 | void test(boost::mpl::true_) |
332 | { |
333 | f(arg); |
334 | } |
335 | |
336 | #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ |
337 | && BOOST_WORKAROUND(__GNUC__, > 3))) |
338 | // Declare a dummy construktor to make gcc happy. |
339 | // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. |
340 | // (warning: non-static reference "const double& boost::UnaryFunction<YourClassHere>::arg" |
341 | // in class without a constructor [-Wuninitialized]) |
342 | UnaryFunction(); |
343 | #endif |
344 | |
345 | Func f; |
346 | Arg arg; |
347 | }; |
348 | |
349 | BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) |
350 | { |
351 | BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); } |
352 | private: |
353 | void test(boost::mpl::false_) |
354 | { |
355 | f(first,second); |
356 | Return r = f(first, second); // require operator() |
357 | (void)r; |
358 | } |
359 | |
360 | void test(boost::mpl::true_) |
361 | { |
362 | f(first,second); |
363 | } |
364 | |
365 | #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ |
366 | && BOOST_WORKAROUND(__GNUC__, > 3))) |
367 | // Declare a dummy constructor to make gcc happy. |
368 | // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. |
369 | // (warning: non-static reference "const double& boost::BinaryFunction<YourClassHere>::arg" |
370 | // in class without a constructor [-Wuninitialized]) |
371 | BinaryFunction(); |
372 | #endif |
373 | |
374 | Func f; |
375 | First first; |
376 | Second second; |
377 | }; |
378 | |
379 | BOOST_concept(UnaryPredicate,(Func)(Arg)) |
380 | { |
381 | BOOST_CONCEPT_USAGE(UnaryPredicate) { |
382 | require_boolean_expr(f(arg)); // require operator() returning bool |
383 | } |
384 | private: |
385 | #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ |
386 | && BOOST_WORKAROUND(__GNUC__, > 3))) |
387 | // Declare a dummy constructor to make gcc happy. |
388 | // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. |
389 | // (warning: non-static reference "const double& boost::UnaryPredicate<YourClassHere>::arg" |
390 | // in class without a constructor [-Wuninitialized]) |
391 | UnaryPredicate(); |
392 | #endif |
393 | |
394 | Func f; |
395 | Arg arg; |
396 | }; |
397 | |
398 | BOOST_concept(BinaryPredicate,(Func)(First)(Second)) |
399 | { |
400 | BOOST_CONCEPT_USAGE(BinaryPredicate) { |
401 | require_boolean_expr(f(a, b)); // require operator() returning bool |
402 | } |
403 | private: |
404 | #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ |
405 | && BOOST_WORKAROUND(__GNUC__, > 3))) |
406 | // Declare a dummy constructor to make gcc happy. |
407 | // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. |
408 | // (warning: non-static reference "const double& boost::BinaryPredicate<YourClassHere>::arg" |
409 | // in class without a constructor [-Wuninitialized]) |
410 | BinaryPredicate(); |
411 | #endif |
412 | Func f; |
413 | First a; |
414 | Second b; |
415 | }; |
416 | |
417 | // use this when functor is used inside a container class like std::set |
418 | BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) |
419 | : BinaryPredicate<Func, First, Second> |
420 | { |
421 | BOOST_CONCEPT_USAGE(Const_BinaryPredicate) { |
422 | const_constraints(f); |
423 | } |
424 | private: |
425 | void const_constraints(const Func& fun) { |
426 | // operator() must be a const member function |
427 | require_boolean_expr(fun(a, b)); |
428 | } |
429 | #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ |
430 | && BOOST_WORKAROUND(__GNUC__, > 3))) |
431 | // Declare a dummy constructor to make gcc happy. |
432 | // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. |
433 | // (warning: non-static reference "const double& boost::Const_BinaryPredicate<YourClassHere>::arg" |
434 | // in class without a constructor [-Wuninitialized]) |
435 | Const_BinaryPredicate(); |
436 | #endif |
437 | |
438 | Func f; |
439 | First a; |
440 | Second b; |
441 | }; |
442 | |
443 | BOOST_concept(AdaptableGenerator,(Func)(Return)) |
444 | : Generator<Func, typename Func::result_type> |
445 | { |
446 | typedef typename Func::result_type result_type; |
447 | |
448 | BOOST_CONCEPT_USAGE(AdaptableGenerator) |
449 | { |
450 | BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); |
451 | } |
452 | }; |
453 | |
454 | BOOST_concept(AdaptableUnaryFunction,(Func)(Return)(Arg)) |
455 | : UnaryFunction<Func, typename Func::result_type, typename Func::argument_type> |
456 | { |
457 | typedef typename Func::argument_type argument_type; |
458 | typedef typename Func::result_type result_type; |
459 | |
460 | ~AdaptableUnaryFunction() |
461 | { |
462 | BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); |
463 | BOOST_CONCEPT_ASSERT((Convertible<Arg, argument_type>)); |
464 | } |
465 | }; |
466 | |
467 | BOOST_concept(AdaptableBinaryFunction,(Func)(Return)(First)(Second)) |
468 | : BinaryFunction< |
469 | Func |
470 | , typename Func::result_type |
471 | , typename Func::first_argument_type |
472 | , typename Func::second_argument_type |
473 | > |
474 | { |
475 | typedef typename Func::first_argument_type first_argument_type; |
476 | typedef typename Func::second_argument_type second_argument_type; |
477 | typedef typename Func::result_type result_type; |
478 | |
479 | ~AdaptableBinaryFunction() |
480 | { |
481 | BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); |
482 | BOOST_CONCEPT_ASSERT((Convertible<First, first_argument_type>)); |
483 | BOOST_CONCEPT_ASSERT((Convertible<Second, second_argument_type>)); |
484 | } |
485 | }; |
486 | |
487 | BOOST_concept(AdaptablePredicate,(Func)(Arg)) |
488 | : UnaryPredicate<Func, Arg> |
489 | , AdaptableUnaryFunction<Func, bool, Arg> |
490 | { |
491 | }; |
492 | |
493 | BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second)) |
494 | : BinaryPredicate<Func, First, Second> |
495 | , AdaptableBinaryFunction<Func, bool, First, Second> |
496 | { |
497 | }; |
498 | |
499 | //=========================================================================== |
500 | // Iterator Concepts |
501 | |
502 | BOOST_concept(InputIterator,(TT)) |
503 | : Assignable<TT> |
504 | , EqualityComparable<TT> |
505 | { |
506 | typedef typename std::iterator_traits<TT>::value_type value_type; |
507 | typedef typename std::iterator_traits<TT>::difference_type difference_type; |
508 | typedef typename std::iterator_traits<TT>::reference reference; |
509 | typedef typename std::iterator_traits<TT>::pointer pointer; |
510 | typedef typename std::iterator_traits<TT>::iterator_category iterator_category; |
511 | |
512 | BOOST_CONCEPT_USAGE(InputIterator) |
513 | { |
514 | BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>)); |
515 | BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>)); |
516 | |
517 | TT j(i); |
518 | (void)*i; // require dereference operator |
519 | ++j; // require preincrement operator |
520 | i++; // require postincrement operator |
521 | } |
522 | private: |
523 | TT i; |
524 | }; |
525 | |
526 | BOOST_concept(OutputIterator,(TT)(ValueT)) |
527 | : Assignable<TT> |
528 | { |
529 | BOOST_CONCEPT_USAGE(OutputIterator) { |
530 | |
531 | ++i; // require preincrement operator |
532 | i++; // require postincrement operator |
533 | *i++ = t; // require postincrement and assignment |
534 | } |
535 | private: |
536 | TT i, j; |
537 | ValueT t; |
538 | }; |
539 | |
540 | BOOST_concept(ForwardIterator,(TT)) |
541 | : InputIterator<TT> |
542 | { |
543 | BOOST_CONCEPT_USAGE(ForwardIterator) |
544 | { |
545 | BOOST_CONCEPT_ASSERT((Convertible< |
546 | BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category |
547 | , std::forward_iterator_tag |
548 | >)); |
549 | |
550 | typename InputIterator<TT>::reference r = *i; |
551 | ignore_unused_variable_warning(r); |
552 | } |
553 | |
554 | private: |
555 | TT i; |
556 | }; |
557 | |
558 | BOOST_concept(Mutable_ForwardIterator,(TT)) |
559 | : ForwardIterator<TT> |
560 | { |
561 | BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) { |
562 | *i++ = *j; // require postincrement and assignment |
563 | } |
564 | private: |
565 | TT i, j; |
566 | }; |
567 | |
568 | BOOST_concept(BidirectionalIterator,(TT)) |
569 | : ForwardIterator<TT> |
570 | { |
571 | BOOST_CONCEPT_USAGE(BidirectionalIterator) |
572 | { |
573 | BOOST_CONCEPT_ASSERT((Convertible< |
574 | BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category |
575 | , std::bidirectional_iterator_tag |
576 | >)); |
577 | |
578 | --i; // require predecrement operator |
579 | i--; // require postdecrement operator |
580 | } |
581 | private: |
582 | TT i; |
583 | }; |
584 | |
585 | BOOST_concept(Mutable_BidirectionalIterator,(TT)) |
586 | : BidirectionalIterator<TT> |
587 | , Mutable_ForwardIterator<TT> |
588 | { |
589 | BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator) |
590 | { |
591 | *i-- = *j; // require postdecrement and assignment |
592 | } |
593 | private: |
594 | TT i, j; |
595 | }; |
596 | |
597 | BOOST_concept(RandomAccessIterator,(TT)) |
598 | : BidirectionalIterator<TT> |
599 | , Comparable<TT> |
600 | { |
601 | BOOST_CONCEPT_USAGE(RandomAccessIterator) |
602 | { |
603 | BOOST_CONCEPT_ASSERT((Convertible< |
604 | BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category |
605 | , std::random_access_iterator_tag |
606 | >)); |
607 | |
608 | i += n; // require assignment addition operator |
609 | i = i + n; i = n + i; // require addition with difference type |
610 | i -= n; // require assignment subtraction operator |
611 | i = i - n; // require subtraction with difference type |
612 | n = i - j; // require difference operator |
613 | (void)i[n]; // require element access operator |
614 | } |
615 | |
616 | private: |
617 | TT a, b; |
618 | TT i, j; |
619 | typename std::iterator_traits<TT>::difference_type n; |
620 | }; |
621 | |
622 | BOOST_concept(Mutable_RandomAccessIterator,(TT)) |
623 | : RandomAccessIterator<TT> |
624 | , Mutable_BidirectionalIterator<TT> |
625 | { |
626 | BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator) |
627 | { |
628 | i[n] = *i; // require element access and assignment |
629 | } |
630 | private: |
631 | TT i; |
632 | typename std::iterator_traits<TT>::difference_type n; |
633 | }; |
634 | |
635 | //=========================================================================== |
636 | // Container s |
637 | |
638 | BOOST_concept(Container,(C)) |
639 | : Assignable<C> |
640 | { |
641 | typedef typename C::value_type value_type; |
642 | typedef typename C::difference_type difference_type; |
643 | typedef typename C::size_type size_type; |
644 | typedef typename C::const_reference const_reference; |
645 | typedef typename C::const_pointer const_pointer; |
646 | typedef typename C::const_iterator const_iterator; |
647 | |
648 | BOOST_CONCEPT_USAGE(Container) |
649 | { |
650 | BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>)); |
651 | const_constraints(c); |
652 | } |
653 | |
654 | private: |
655 | void const_constraints(const C& cc) { |
656 | i = cc.begin(); |
657 | i = cc.end(); |
658 | n = cc.size(); |
659 | n = cc.max_size(); |
660 | b = cc.empty(); |
661 | } |
662 | C c; |
663 | bool b; |
664 | const_iterator i; |
665 | size_type n; |
666 | }; |
667 | |
668 | BOOST_concept(Mutable_Container,(C)) |
669 | : Container<C> |
670 | { |
671 | typedef typename C::reference reference; |
672 | typedef typename C::iterator iterator; |
673 | typedef typename C::pointer pointer; |
674 | |
675 | BOOST_CONCEPT_USAGE(Mutable_Container) |
676 | { |
677 | BOOST_CONCEPT_ASSERT(( |
678 | Assignable<typename Mutable_Container::value_type>)); |
679 | |
680 | BOOST_CONCEPT_ASSERT((InputIterator<iterator>)); |
681 | |
682 | i = c.begin(); |
683 | i = c.end(); |
684 | c.swap(c2); |
685 | } |
686 | |
687 | private: |
688 | iterator i; |
689 | C c, c2; |
690 | }; |
691 | |
692 | BOOST_concept(ForwardContainer,(C)) |
693 | : Container<C> |
694 | { |
695 | BOOST_CONCEPT_USAGE(ForwardContainer) |
696 | { |
697 | BOOST_CONCEPT_ASSERT(( |
698 | ForwardIterator< |
699 | typename ForwardContainer::const_iterator |
700 | >)); |
701 | } |
702 | }; |
703 | |
704 | BOOST_concept(Mutable_ForwardContainer,(C)) |
705 | : ForwardContainer<C> |
706 | , Mutable_Container<C> |
707 | { |
708 | BOOST_CONCEPT_USAGE(Mutable_ForwardContainer) |
709 | { |
710 | BOOST_CONCEPT_ASSERT(( |
711 | Mutable_ForwardIterator< |
712 | typename Mutable_ForwardContainer::iterator |
713 | >)); |
714 | } |
715 | }; |
716 | |
717 | BOOST_concept(ReversibleContainer,(C)) |
718 | : ForwardContainer<C> |
719 | { |
720 | typedef typename |
721 | C::const_reverse_iterator |
722 | const_reverse_iterator; |
723 | |
724 | BOOST_CONCEPT_USAGE(ReversibleContainer) |
725 | { |
726 | BOOST_CONCEPT_ASSERT(( |
727 | BidirectionalIterator< |
728 | typename ReversibleContainer::const_iterator>)); |
729 | |
730 | BOOST_CONCEPT_ASSERT((BidirectionalIterator<const_reverse_iterator>)); |
731 | |
732 | const_constraints(c); |
733 | } |
734 | private: |
735 | void const_constraints(const C& cc) |
736 | { |
737 | const_reverse_iterator i = cc.rbegin(); |
738 | i = cc.rend(); |
739 | } |
740 | C c; |
741 | }; |
742 | |
743 | BOOST_concept(Mutable_ReversibleContainer,(C)) |
744 | : Mutable_ForwardContainer<C> |
745 | , ReversibleContainer<C> |
746 | { |
747 | typedef typename C::reverse_iterator reverse_iterator; |
748 | |
749 | BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer) |
750 | { |
751 | typedef typename Mutable_ForwardContainer<C>::iterator iterator; |
752 | BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>)); |
753 | BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<reverse_iterator>)); |
754 | |
755 | reverse_iterator i = c.rbegin(); |
756 | i = c.rend(); |
757 | } |
758 | private: |
759 | C c; |
760 | }; |
761 | |
762 | BOOST_concept(RandomAccessContainer,(C)) |
763 | : ReversibleContainer<C> |
764 | { |
765 | typedef typename C::size_type size_type; |
766 | typedef typename C::const_reference const_reference; |
767 | |
768 | BOOST_CONCEPT_USAGE(RandomAccessContainer) |
769 | { |
770 | BOOST_CONCEPT_ASSERT(( |
771 | RandomAccessIterator< |
772 | typename RandomAccessContainer::const_iterator |
773 | >)); |
774 | |
775 | const_constraints(c); |
776 | } |
777 | private: |
778 | void const_constraints(const C& cc) |
779 | { |
780 | const_reference r = cc[n]; |
781 | ignore_unused_variable_warning(r); |
782 | } |
783 | |
784 | C c; |
785 | size_type n; |
786 | }; |
787 | |
788 | BOOST_concept(Mutable_RandomAccessContainer,(C)) |
789 | : Mutable_ReversibleContainer<C> |
790 | , RandomAccessContainer<C> |
791 | { |
792 | private: |
793 | typedef Mutable_RandomAccessContainer self; |
794 | public: |
795 | BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer) |
796 | { |
797 | BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>)); |
798 | BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_iterator>)); |
799 | |
800 | typename self::reference r = c[i]; |
801 | ignore_unused_variable_warning(r); |
802 | } |
803 | |
804 | private: |
805 | typename Mutable_ReversibleContainer<C>::size_type i; |
806 | C c; |
807 | }; |
808 | |
809 | // A Sequence is inherently mutable |
810 | BOOST_concept(Sequence,(S)) |
811 | : Mutable_ForwardContainer<S> |
812 | // Matt Austern's book puts DefaultConstructible here, the C++ |
813 | // standard places it in Container --JGS |
814 | // ... so why aren't we following the standard? --DWA |
815 | , DefaultConstructible<S> |
816 | { |
817 | BOOST_CONCEPT_USAGE(Sequence) |
818 | { |
819 | S |
820 | c(n, t), |
821 | c2(first, last); |
822 | |
823 | c.insert(p, t); |
824 | c.insert(p, n, t); |
825 | c.insert(p, first, last); |
826 | |
827 | c.erase(p); |
828 | c.erase(p, q); |
829 | |
830 | typename Sequence::reference r = c.front(); |
831 | |
832 | ignore_unused_variable_warning(c); |
833 | ignore_unused_variable_warning(c2); |
834 | ignore_unused_variable_warning(r); |
835 | const_constraints(c); |
836 | } |
837 | private: |
838 | void const_constraints(const S& c) { |
839 | typename Sequence::const_reference r = c.front(); |
840 | ignore_unused_variable_warning(r); |
841 | } |
842 | |
843 | typename S::value_type t; |
844 | typename S::size_type n; |
845 | typename S::value_type* first, *last; |
846 | typename S::iterator p, q; |
847 | }; |
848 | |
849 | BOOST_concept(FrontInsertionSequence,(S)) |
850 | : Sequence<S> |
851 | { |
852 | BOOST_CONCEPT_USAGE(FrontInsertionSequence) |
853 | { |
854 | c.push_front(t); |
855 | c.pop_front(); |
856 | } |
857 | private: |
858 | S c; |
859 | typename S::value_type t; |
860 | }; |
861 | |
862 | BOOST_concept(BackInsertionSequence,(S)) |
863 | : Sequence<S> |
864 | { |
865 | BOOST_CONCEPT_USAGE(BackInsertionSequence) |
866 | { |
867 | c.push_back(t); |
868 | c.pop_back(); |
869 | typename BackInsertionSequence::reference r = c.back(); |
870 | ignore_unused_variable_warning(r); |
871 | const_constraints(c); |
872 | } |
873 | private: |
874 | void const_constraints(const S& cc) { |
875 | typename BackInsertionSequence::const_reference |
876 | r = cc.back(); |
877 | ignore_unused_variable_warning(r); |
878 | } |
879 | S c; |
880 | typename S::value_type t; |
881 | }; |
882 | |
883 | BOOST_concept(AssociativeContainer,(C)) |
884 | : ForwardContainer<C> |
885 | , DefaultConstructible<C> |
886 | { |
887 | typedef typename C::key_type key_type; |
888 | typedef typename C::key_compare key_compare; |
889 | typedef typename C::value_compare value_compare; |
890 | typedef typename C::iterator iterator; |
891 | |
892 | BOOST_CONCEPT_USAGE(AssociativeContainer) |
893 | { |
894 | i = c.find(k); |
895 | r = c.equal_range(k); |
896 | c.erase(k); |
897 | c.erase(i); |
898 | c.erase(r.first, r.second); |
899 | const_constraints(c); |
900 | BOOST_CONCEPT_ASSERT((BinaryPredicate<key_compare,key_type,key_type>)); |
901 | |
902 | typedef typename AssociativeContainer::value_type value_type_; |
903 | BOOST_CONCEPT_ASSERT((BinaryPredicate<value_compare,value_type_,value_type_>)); |
904 | } |
905 | |
906 | // Redundant with the base concept, but it helps below. |
907 | typedef typename C::const_iterator const_iterator; |
908 | private: |
909 | void const_constraints(const C& cc) |
910 | { |
911 | ci = cc.find(k); |
912 | n = cc.count(k); |
913 | cr = cc.equal_range(k); |
914 | } |
915 | |
916 | C c; |
917 | iterator i; |
918 | std::pair<iterator,iterator> r; |
919 | const_iterator ci; |
920 | std::pair<const_iterator,const_iterator> cr; |
921 | typename C::key_type k; |
922 | typename C::size_type n; |
923 | }; |
924 | |
925 | BOOST_concept(UniqueAssociativeContainer,(C)) |
926 | : AssociativeContainer<C> |
927 | { |
928 | BOOST_CONCEPT_USAGE(UniqueAssociativeContainer) |
929 | { |
930 | C c(first, last); |
931 | |
932 | pos_flag = c.insert(t); |
933 | c.insert(first, last); |
934 | |
935 | ignore_unused_variable_warning(c); |
936 | } |
937 | private: |
938 | std::pair<typename C::iterator, bool> pos_flag; |
939 | typename C::value_type t; |
940 | typename C::value_type* first, *last; |
941 | }; |
942 | |
943 | BOOST_concept(MultipleAssociativeContainer,(C)) |
944 | : AssociativeContainer<C> |
945 | { |
946 | BOOST_CONCEPT_USAGE(MultipleAssociativeContainer) |
947 | { |
948 | C c(first, last); |
949 | |
950 | pos = c.insert(t); |
951 | c.insert(first, last); |
952 | |
953 | ignore_unused_variable_warning(c); |
954 | ignore_unused_variable_warning(pos); |
955 | } |
956 | private: |
957 | typename C::iterator pos; |
958 | typename C::value_type t; |
959 | typename C::value_type* first, *last; |
960 | }; |
961 | |
962 | BOOST_concept(SimpleAssociativeContainer,(C)) |
963 | : AssociativeContainer<C> |
964 | { |
965 | BOOST_CONCEPT_USAGE(SimpleAssociativeContainer) |
966 | { |
967 | typedef typename C::key_type key_type; |
968 | typedef typename C::value_type value_type; |
969 | BOOST_MPL_ASSERT((boost::is_same<key_type,value_type>)); |
970 | } |
971 | }; |
972 | |
973 | BOOST_concept(PairAssociativeContainer,(C)) |
974 | : AssociativeContainer<C> |
975 | { |
976 | BOOST_CONCEPT_USAGE(PairAssociativeContainer) |
977 | { |
978 | typedef typename C::key_type key_type; |
979 | typedef typename C::value_type value_type; |
980 | typedef typename C::mapped_type mapped_type; |
981 | typedef std::pair<const key_type, mapped_type> required_value_type; |
982 | BOOST_MPL_ASSERT((boost::is_same<value_type,required_value_type>)); |
983 | } |
984 | }; |
985 | |
986 | BOOST_concept(SortedAssociativeContainer,(C)) |
987 | : AssociativeContainer<C> |
988 | , ReversibleContainer<C> |
989 | { |
990 | BOOST_CONCEPT_USAGE(SortedAssociativeContainer) |
991 | { |
992 | C |
993 | c(kc), |
994 | c2(first, last), |
995 | c3(first, last, kc); |
996 | |
997 | p = c.upper_bound(k); |
998 | p = c.lower_bound(k); |
999 | r = c.equal_range(k); |
1000 | |
1001 | c.insert(p, t); |
1002 | |
1003 | ignore_unused_variable_warning(c); |
1004 | ignore_unused_variable_warning(c2); |
1005 | ignore_unused_variable_warning(c3); |
1006 | const_constraints(c); |
1007 | } |
1008 | |
1009 | void const_constraints(const C& c) |
1010 | { |
1011 | kc = c.key_comp(); |
1012 | vc = c.value_comp(); |
1013 | |
1014 | cp = c.upper_bound(k); |
1015 | cp = c.lower_bound(k); |
1016 | cr = c.equal_range(k); |
1017 | } |
1018 | |
1019 | private: |
1020 | typename C::key_compare kc; |
1021 | typename C::value_compare vc; |
1022 | typename C::value_type t; |
1023 | typename C::key_type k; |
1024 | typedef typename C::iterator iterator; |
1025 | typedef typename C::const_iterator const_iterator; |
1026 | |
1027 | typedef SortedAssociativeContainer self; |
1028 | iterator p; |
1029 | const_iterator cp; |
1030 | std::pair<typename self::iterator,typename self::iterator> r; |
1031 | std::pair<typename self::const_iterator,typename self::const_iterator> cr; |
1032 | typename C::value_type* first, *last; |
1033 | }; |
1034 | |
1035 | // HashedAssociativeContainer |
1036 | |
1037 | BOOST_concept(Collection,(C)) |
1038 | { |
1039 | BOOST_CONCEPT_USAGE(Collection) |
1040 | { |
1041 | boost::function_requires<boost::InputIteratorConcept<iterator> >(); |
1042 | boost::function_requires<boost::InputIteratorConcept<const_iterator> >(); |
1043 | boost::function_requires<boost::CopyConstructibleConcept<value_type> >(); |
1044 | const_constraints(c); |
1045 | i = c.begin(); |
1046 | i = c.end(); |
1047 | c.swap(c); |
1048 | } |
1049 | |
1050 | void const_constraints(const C& cc) { |
1051 | ci = cc.begin(); |
1052 | ci = cc.end(); |
1053 | n = cc.size(); |
1054 | b = cc.empty(); |
1055 | } |
1056 | |
1057 | private: |
1058 | typedef typename C::value_type value_type; |
1059 | typedef typename C::iterator iterator; |
1060 | typedef typename C::const_iterator const_iterator; |
1061 | typedef typename C::reference reference; |
1062 | typedef typename C::const_reference const_reference; |
1063 | // typedef typename C::pointer pointer; |
1064 | typedef typename C::difference_type difference_type; |
1065 | typedef typename C::size_type size_type; |
1066 | |
1067 | C c; |
1068 | bool b; |
1069 | iterator i; |
1070 | const_iterator ci; |
1071 | size_type n; |
1072 | }; |
1073 | } // namespace boost |
1074 | |
1075 | #if (defined _MSC_VER) |
1076 | # pragma warning( pop ) |
1077 | #endif |
1078 | |
1079 | # include <boost/concept/detail/concept_undef.hpp> |
1080 | |
1081 | #endif // BOOST_CONCEPT_CHECKS_HPP |
1082 | |
1083 | |