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