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