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