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