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