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