]> git.lyx.org Git - lyx.git/blob - boost/boost/concept_check.hpp
small stuff, whitespace & consistent naming
[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/type.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(type<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 TrivialIteratorConcept
540   {
541     void constraints() {
542       function_requires< AssignableConcept<TT> >();
543       function_requires< DefaultConstructibleConcept<TT> >();
544       function_requires< EqualityComparableConcept<TT> >();
545       (void)*i;           // require dereference operator
546     }
547     TT i;
548   };
549
550   template <class TT>
551   struct Mutable_TrivialIteratorConcept
552   {
553     void constraints() {
554       function_requires< TrivialIteratorConcept<TT> >();
555       *i = *j;            // require dereference and assignment
556     }
557     TT i, j;
558   };
559
560   template <class TT>
561   struct InputIteratorConcept
562   {
563     void constraints() {
564       function_requires< TrivialIteratorConcept<TT> >();
565       // require iterator_traits typedef's
566 #ifndef BOOST_NO_STD_ITERATOR_TRAITS
567       typedef typename std::iterator_traits<TT>::difference_type D;
568       // Hmm, the following is a bit fragile
569       //function_requires< SignedIntegerConcept<D> >();
570       typedef typename std::iterator_traits<TT>::reference R;
571       typedef typename std::iterator_traits<TT>::pointer P;
572       typedef typename std::iterator_traits<TT>::iterator_category C;
573       function_requires< ConvertibleConcept<C, std::input_iterator_tag> >();
574 #endif
575       ++i;                // require preincrement operator
576       i++;                // require postincrement operator
577     }
578     TT i;
579   };
580
581   template <class TT, class ValueT>
582   struct OutputIteratorConcept
583   {
584     void constraints() {
585       function_requires< AssignableConcept<TT> >();
586       ++i;                // require preincrement operator
587       i++;                // require postincrement operator
588       *i++ = t;           // require postincrement and assignment
589     }
590     TT i, j;
591     ValueT t;
592   };
593
594   template <class TT>
595   struct ForwardIteratorConcept
596   {
597     void constraints() {
598       function_requires< InputIteratorConcept<TT> >();
599 #ifndef BOOST_NO_STD_ITERATOR_TRAITS
600       typedef typename std::iterator_traits<TT>::iterator_category C;
601       function_requires< ConvertibleConcept<C, std::forward_iterator_tag> >();
602       typedef typename std::iterator_traits<TT>::reference reference;
603       reference r = *i;
604       ignore_unused_variable_warning(r);
605 #endif
606     }
607     TT i;
608   };
609
610   template <class TT>
611   struct Mutable_ForwardIteratorConcept
612   {
613     void constraints() {
614       function_requires< ForwardIteratorConcept<TT> >();
615       *i++ = *i;         // require postincrement and assignment
616     }
617     TT i;
618   };
619
620   template <class TT>
621   struct BidirectionalIteratorConcept
622   {
623     void constraints() {
624       function_requires< ForwardIteratorConcept<TT> >();
625 #ifndef BOOST_NO_STD_ITERATOR_TRAITS
626       typedef typename std::iterator_traits<TT>::iterator_category C;
627       function_requires< ConvertibleConcept<C, 
628         std::bidirectional_iterator_tag> >();
629 #endif
630       --i;                // require predecrement operator
631       i--;                // require postdecrement operator
632     }
633     TT i;
634   };
635
636   template <class TT>
637   struct Mutable_BidirectionalIteratorConcept
638   {
639     void constraints() {
640       function_requires< BidirectionalIteratorConcept<TT> >();
641       function_requires< Mutable_ForwardIteratorConcept<TT> >();
642       *i-- = *i;                  // require postdecrement and assignment
643     }
644     TT i;
645   };
646
647
648   template <class TT>
649   struct RandomAccessIteratorConcept
650   {
651     void constraints() {
652       function_requires< BidirectionalIteratorConcept<TT> >();
653       function_requires< ComparableConcept<TT> >();
654 #ifndef BOOST_NO_STD_ITERATOR_TRAITS
655       typedef typename std::iterator_traits<TT>::iterator_category C;
656       function_requires< ConvertibleConcept< C,
657         std::random_access_iterator_tag> >();
658       typedef typename std::iterator_traits<TT>::reference R;
659 #endif
660
661       i += n;             // require assignment addition operator
662       i = i + n; i = n + i; // require addition with difference type
663       i -= n;             // require assignment subtraction operator
664       i = i - n;                  // require subtraction with difference type
665       n = i - j;                  // require difference operator
666       (void)i[n];                 // require element access operator
667     }
668     TT a, b;
669     TT i, j;
670 #ifndef BOOST_NO_STD_ITERATOR_TRAITS
671     typename std::iterator_traits<TT>::difference_type n;
672 #else
673     std::ptrdiff_t n;
674 #endif
675   };
676
677   template <class TT>
678   struct Mutable_RandomAccessIteratorConcept
679   {
680     void constraints() {
681       function_requires< RandomAccessIteratorConcept<TT> >();
682       function_requires< Mutable_BidirectionalIteratorConcept<TT> >();
683       i[n] = *i;                  // require element access and assignment
684     }
685     TT i;
686 #ifndef BOOST_NO_STD_ITERATOR_TRAITS
687     typename std::iterator_traits<TT>::difference_type n;
688 #else
689     std::ptrdiff_t n;
690 #endif
691   };
692
693   //===========================================================================
694   // Container Concepts
695
696   template <class Container>
697   struct ContainerConcept
698   {
699     typedef typename Container::value_type value_type;
700     typedef typename Container::difference_type difference_type;
701     typedef typename Container::size_type size_type;
702     typedef typename Container::const_reference const_reference;
703     typedef typename Container::const_pointer const_pointer;
704     typedef typename Container::const_iterator const_iterator;
705
706     void constraints() {
707       function_requires< InputIteratorConcept<const_iterator> >();
708       function_requires< AssignableConcept<Container> >();
709       const_constraints(c);
710     }
711     void const_constraints(const Container& c) {
712       i = c.begin();
713       i = c.end();
714       n = c.size();
715       n = c.max_size();
716       b = c.empty();
717     }
718     Container c;
719     bool b;
720     const_iterator i;
721     size_type n;
722   };
723
724   template <class Container>
725   struct Mutable_ContainerConcept
726   {
727     typedef typename Container::value_type value_type;
728     typedef typename Container::reference reference;
729     typedef typename Container::iterator iterator;
730     typedef typename Container::pointer pointer;
731     
732     void constraints() {
733       function_requires< ContainerConcept<Container> >();
734       function_requires< AssignableConcept<value_type> >();
735       function_requires< InputIteratorConcept<iterator> >();
736
737       i = c.begin();
738       i = c.end();
739       c.swap(c2);
740     }
741     iterator i;
742     Container c, c2;
743   };
744
745   template <class ForwardContainer>
746   struct ForwardContainerConcept
747   {
748     void constraints() {
749       function_requires< ContainerConcept<ForwardContainer> >();
750       typedef typename ForwardContainer::const_iterator const_iterator;
751       function_requires< ForwardIteratorConcept<const_iterator> >();
752     }
753   };  
754
755   template <class ForwardContainer>
756   struct Mutable_ForwardContainerConcept
757   {
758     void constraints() {
759       function_requires< ForwardContainerConcept<ForwardContainer> >();
760       function_requires< Mutable_ContainerConcept<ForwardContainer> >();
761       typedef typename ForwardContainer::iterator iterator;
762       function_requires< Mutable_ForwardIteratorConcept<iterator> >();
763     }
764   };  
765
766   template <class ReversibleContainer>
767   struct ReversibleContainerConcept
768   {
769     typedef typename ReversibleContainer::const_iterator const_iterator;
770     typedef typename ReversibleContainer::const_reverse_iterator
771       const_reverse_iterator;
772
773     void constraints() {
774       function_requires< ForwardContainerConcept<ReversibleContainer> >();
775       function_requires< BidirectionalIteratorConcept<const_iterator> >();
776       function_requires< 
777         BidirectionalIteratorConcept<const_reverse_iterator> >();
778       const_constraints(c);
779     }
780     void const_constraints(const ReversibleContainer& c) {
781       const_reverse_iterator i = c.rbegin();
782       i = c.rend();
783     }
784     ReversibleContainer c;
785   };
786
787   template <class ReversibleContainer>
788   struct Mutable_ReversibleContainerConcept
789   {
790     typedef typename ReversibleContainer::iterator iterator;
791     typedef typename ReversibleContainer::reverse_iterator reverse_iterator;
792
793     void constraints() {
794       function_requires< ReversibleContainerConcept<ReversibleContainer> >();
795       function_requires<
796         Mutable_ForwardContainerConcept<ReversibleContainer> >();
797       function_requires< Mutable_BidirectionalIteratorConcept<iterator> >();
798       function_requires<
799         Mutable_BidirectionalIteratorConcept<reverse_iterator> >();
800
801       reverse_iterator i = c.rbegin();
802       i = c.rend();
803     }
804     ReversibleContainer c;
805   };
806
807   template <class RandomAccessContainer>
808   struct RandomAccessContainerConcept
809   {
810     typedef typename RandomAccessContainer::size_type size_type;
811     typedef typename RandomAccessContainer::const_reference const_reference;
812     typedef typename RandomAccessContainer::const_iterator const_iterator;
813     typedef typename RandomAccessContainer::const_reverse_iterator
814       const_reverse_iterator;
815
816     void constraints() {
817       function_requires< ReversibleContainerConcept<RandomAccessContainer> >();
818       function_requires< RandomAccessIteratorConcept<const_iterator> >();
819       function_requires<
820         RandomAccessIteratorConcept<const_reverse_iterator> >();
821
822       const_constraints(c);
823     }
824     void const_constraints(const RandomAccessContainer& c) {
825       const_reference r = c[n];
826       ignore_unused_variable_warning(r);
827     }
828     RandomAccessContainer c;
829     size_type n;
830   };
831
832   template <class RandomAccessContainer>
833   struct Mutable_RandomAccessContainerConcept
834   {
835     typedef typename RandomAccessContainer::size_type size_type;
836     typedef typename RandomAccessContainer::reference reference;
837     typedef typename RandomAccessContainer::iterator iterator;
838     typedef typename RandomAccessContainer::reverse_iterator reverse_iterator;
839
840     void constraints() {
841       function_requires<
842         RandomAccessContainerConcept<RandomAccessContainer> >();
843       function_requires<
844         Mutable_ReversibleContainerConcept<RandomAccessContainer> >();
845       function_requires< Mutable_RandomAccessIteratorConcept<iterator> >();
846       function_requires<
847         Mutable_RandomAccessIteratorConcept<reverse_iterator> >();
848
849       reference r = c[i];
850       ignore_unused_variable_warning(r);
851     }
852     size_type i;
853     RandomAccessContainer c;
854   };
855
856   // A Sequence is inherently mutable
857   template <class Sequence>
858   struct SequenceConcept
859   {
860
861     typedef typename Sequence::reference reference;
862     typedef typename Sequence::const_reference const_reference;
863
864     void constraints() {
865       // Matt Austern's book puts DefaultConstructible here, the C++
866       // standard places it in Container
867       //    function_requires< DefaultConstructible<Sequence> >();
868       function_requires< Mutable_ForwardContainerConcept<Sequence> >();
869       function_requires< DefaultConstructibleConcept<Sequence> >();
870
871       Sequence 
872         c(n),
873         c2(n, t),
874         c3(first, last);
875
876       c.insert(p, t);
877       c.insert(p, n, t);
878       c.insert(p, first, last);
879
880       c.erase(p);
881       c.erase(p, q);
882
883       reference r = c.front();
884
885       ignore_unused_variable_warning(c);
886       ignore_unused_variable_warning(c2);
887       ignore_unused_variable_warning(c3);
888       ignore_unused_variable_warning(r);
889       const_constraints(c);
890     }
891     void const_constraints(const Sequence& c) {
892       const_reference r = c.front();
893       ignore_unused_variable_warning(r);
894     }
895     typename Sequence::value_type t;
896     typename Sequence::size_type n;
897     typename Sequence::value_type* first, *last;
898     typename Sequence::iterator p, q;
899   };
900
901   template <class FrontInsertionSequence>
902   struct FrontInsertionSequenceConcept
903   {
904     void constraints() {
905       function_requires< SequenceConcept<FrontInsertionSequence> >();
906
907       c.push_front(t);
908       c.pop_front();
909     }
910     FrontInsertionSequence c;
911     typename FrontInsertionSequence::value_type t;
912   };
913
914   template <class BackInsertionSequence>
915   struct BackInsertionSequenceConcept
916   {
917     typedef typename BackInsertionSequence::reference reference;
918     typedef typename BackInsertionSequence::const_reference const_reference;
919
920     void constraints() {
921       function_requires< SequenceConcept<BackInsertionSequence> >();
922
923       c.push_back(t);
924       c.pop_back();
925       reference r = c.back();
926       ignore_unused_variable_warning(r);
927     }
928     void const_constraints(const BackInsertionSequence& c) {
929       const_reference r = c.back();
930       ignore_unused_variable_warning(r);
931     };
932     BackInsertionSequence c;
933     typename BackInsertionSequence::value_type t;
934   };
935
936   template <class AssociativeContainer>
937   struct AssociativeContainerConcept
938   {
939     void constraints() {
940       function_requires< ForwardContainerConcept<AssociativeContainer> >();
941       function_requires< DefaultConstructibleConcept<AssociativeContainer> >();
942     
943       i = c.find(k);
944       r = c.equal_range(k);
945       c.erase(k);
946       c.erase(i);
947       c.erase(r.first, r.second);
948       const_constraints(c);
949     }
950     void const_constraints(const AssociativeContainer& c) {
951       ci = c.find(k);
952       n = c.count(k);
953       cr = c.equal_range(k);
954     }
955     typedef typename AssociativeContainer::iterator iterator;
956     typedef typename AssociativeContainer::const_iterator const_iterator;
957
958     AssociativeContainer c;
959     iterator i;
960     std::pair<iterator,iterator> r;
961     const_iterator ci;
962     std::pair<const_iterator,const_iterator> cr;
963     typename AssociativeContainer::key_type k;
964     typename AssociativeContainer::size_type n;
965   };
966
967   template <class UniqueAssociativeContainer>
968   struct UniqueAssociativeContainerConcept
969   {
970     void constraints() {
971       function_requires< AssociativeContainerConcept<UniqueAssociativeContainer> >();
972     
973       UniqueAssociativeContainer c(first, last);
974       
975       pos_flag = c.insert(t);
976       c.insert(first, last);
977
978       ignore_unused_variable_warning(c);
979     }
980     std::pair<typename UniqueAssociativeContainer::iterator, bool> pos_flag;
981     typename UniqueAssociativeContainer::value_type t;
982     typename UniqueAssociativeContainer::value_type* first, *last;
983   };
984
985   template <class MultipleAssociativeContainer>
986   struct MultipleAssociativeContainerConcept
987   {
988     void constraints() {
989       function_requires< AssociativeContainerConcept<MultipleAssociativeContainer> >();
990
991       MultipleAssociativeContainer c(first, last);
992       
993       pos = c.insert(t);
994       c.insert(first, last);
995
996       ignore_unused_variable_warning(c);
997       ignore_unused_variable_warning(pos);
998     }
999     typename MultipleAssociativeContainer::iterator pos;
1000     typename MultipleAssociativeContainer::value_type t;
1001     typename MultipleAssociativeContainer::value_type* first, *last;
1002   };
1003
1004   template <class SimpleAssociativeContainer>
1005   struct SimpleAssociativeContainerConcept
1006   {
1007     void constraints() {
1008       function_requires< AssociativeContainerConcept<SimpleAssociativeContainer> >();
1009       typedef typename SimpleAssociativeContainer::key_type key_type;
1010       typedef typename SimpleAssociativeContainer::value_type value_type;
1011       typedef typename require_same<key_type, value_type>::type req;
1012     }
1013   };
1014
1015   template <class SimpleAssociativeContainer>
1016   struct PairAssociativeContainerConcept
1017   {
1018     void constraints() {
1019       function_requires< AssociativeContainerConcept<SimpleAssociativeContainer> >();
1020       typedef typename SimpleAssociativeContainer::key_type key_type;
1021       typedef typename SimpleAssociativeContainer::value_type value_type;
1022       typedef typename SimpleAssociativeContainer::mapped_type mapped_type;
1023       typedef std::pair<const key_type, mapped_type> required_value_type;
1024       typedef typename require_same<value_type, required_value_type>::type req;
1025     }
1026   };
1027
1028   template <class SortedAssociativeContainer>
1029   struct SortedAssociativeContainerConcept
1030   {
1031     void constraints() {
1032       function_requires< AssociativeContainerConcept<SortedAssociativeContainer> >();
1033       function_requires< ReversibleContainerConcept<SortedAssociativeContainer> >();
1034
1035       SortedAssociativeContainer 
1036         c(kc),
1037         c2(first, last),
1038         c3(first, last, kc);
1039
1040       p = c.upper_bound(k);
1041       p = c.lower_bound(k);
1042       r = c.equal_range(k);
1043       
1044       c.insert(p, t);
1045       
1046       ignore_unused_variable_warning(c);
1047       ignore_unused_variable_warning(c2);
1048       ignore_unused_variable_warning(c3);
1049     }
1050     void const_constraints(const SortedAssociativeContainer& c) {
1051       kc = c.key_comp();
1052       vc = c.value_comp();
1053
1054       cp = c.upper_bound(k);
1055       cp = c.lower_bound(k);
1056       cr = c.equal_range(k);
1057     }
1058     typename SortedAssociativeContainer::key_compare kc;
1059     typename SortedAssociativeContainer::value_compare vc;
1060     typename SortedAssociativeContainer::value_type t;
1061     typename SortedAssociativeContainer::key_type k;
1062     typedef typename SortedAssociativeContainer::iterator iterator;
1063     typedef typename SortedAssociativeContainer::const_iterator const_iterator;
1064     iterator p;
1065     const_iterator cp;
1066     std::pair<iterator,iterator> r;
1067     std::pair<const_iterator,const_iterator> cr;
1068     typename SortedAssociativeContainer::value_type* first, *last;
1069   };
1070
1071   // HashedAssociativeContainer
1072
1073 } // namespace boost
1074
1075 #endif // BOOST_CONCEPT_CHECKS_HPP
1076