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
40namespace 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