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