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