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)
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)
13 // See http://www.boost.org/libs/concept_check for documentation.
15 #ifndef BOOST_CONCEPT_CHECKS_HPP
16 # define BOOST_CONCEPT_CHECKS_HPP
18 # include <boost/concept/assert.hpp>
20 # include <boost/iterator.hpp>
21 # include <boost/type_traits/conversion_traits.hpp>
23 # include <boost/type_traits/is_same.hpp>
24 # include <boost/type_traits/is_void.hpp>
25 # include <boost/mpl/assert.hpp>
26 # include <boost/mpl/bool.hpp>
27 # include <boost/detail/workaround.hpp>
28 # include <boost/detail/iterator.hpp>
30 # include <boost/concept/usage.hpp>
31 # include <boost/concept/detail/concept_def.hpp>
37 // Backward compatibility
40 template <class Model>
41 inline void function_requires(Model* = 0)
43 BOOST_CONCEPT_ASSERT((Model));
45 template <class T> inline void ignore_unused_variable_warning(T const&) {}
47 # define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
48 BOOST_CONCEPT_ASSERT((ns::concept<type_var>))
50 # define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \
51 BOOST_CONCEPT_ASSERT((ns::concept<type_var1,type_var2>))
53 # define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \
54 BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3>))
56 # define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \
57 BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3,tv4>))
61 // Begin concept definitions
63 BOOST_concept(Integer, (T))
65 BOOST_CONCEPT_USAGE(Integer)
67 x.error_type_must_be_an_integer_type();
73 template <> struct Integer<signed char> {};
74 template <> struct Integer<unsigned char> {};
75 template <> struct Integer<short> {};
76 template <> struct Integer<unsigned short> {};
77 template <> struct Integer<int> {};
78 template <> struct Integer<unsigned int> {};
79 template <> struct Integer<long> {};
80 template <> struct Integer<unsigned long> {};
81 # if defined(BOOST_HAS_LONG_LONG)
82 template <> struct Integer< ::boost::long_long_type> {};
83 template <> struct Integer< ::boost::ulong_long_type> {};
84 # elif defined(BOOST_HAS_MS_INT64)
85 template <> struct Integer<__int64> {};
86 template <> struct Integer<unsigned __int64> {};
89 BOOST_concept(SignedInteger,(T)) {
90 BOOST_CONCEPT_USAGE(SignedInteger) {
91 x.error_type_must_be_a_signed_integer_type();
96 template <> struct SignedInteger<signed char> { };
97 template <> struct SignedInteger<short> {};
98 template <> struct SignedInteger<int> {};
99 template <> struct SignedInteger<long> {};
100 # if defined(BOOST_HAS_LONG_LONG)
101 template <> struct SignedInteger< ::boost::long_long_type> {};
102 # elif defined(BOOST_HAS_MS_INT64)
103 template <> struct SignedInteger<__int64> {};
106 BOOST_concept(UnsignedInteger,(T)) {
107 BOOST_CONCEPT_USAGE(UnsignedInteger) {
108 x.error_type_must_be_an_unsigned_integer_type();
114 template <> struct UnsignedInteger<unsigned char> {};
115 template <> struct UnsignedInteger<unsigned short> {};
116 template <> struct UnsignedInteger<unsigned int> {};
117 template <> struct UnsignedInteger<unsigned long> {};
118 # if defined(BOOST_HAS_LONG_LONG)
119 template <> struct UnsignedInteger< ::boost::ulong_long_type> {};
120 # elif defined(BOOST_HAS_MS_INT64)
121 template <> struct UnsignedInteger<unsigned __int64> {};
124 //===========================================================================
127 BOOST_concept(DefaultConstructible,(TT))
129 BOOST_CONCEPT_USAGE(DefaultConstructible) {
130 TT a; // require default constructor
131 ignore_unused_variable_warning(a);
135 BOOST_concept(Assignable,(TT))
137 BOOST_CONCEPT_USAGE(Assignable) {
138 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
139 a = a; // require assignment operator
141 const_constraints(a);
144 void const_constraints(const TT& b) {
145 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
146 a = b; // const required for argument to assignment
154 BOOST_concept(CopyConstructible,(TT))
156 BOOST_CONCEPT_USAGE(CopyConstructible) {
157 TT a(b); // require copy constructor
158 TT* ptr = &a; // require address of operator
159 const_constraints(a);
160 ignore_unused_variable_warning(ptr);
163 void const_constraints(const TT& a) {
164 TT c(a); // require const copy constructor
165 const TT* ptr = &a; // require const address of operator
166 ignore_unused_variable_warning(c);
167 ignore_unused_variable_warning(ptr);
172 // The SGI STL version of Assignable requires copy constructor and operator=
173 BOOST_concept(SGIAssignable,(TT))
175 BOOST_CONCEPT_USAGE(SGIAssignable) {
177 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
178 a = a; // require assignment operator
180 const_constraints(a);
181 ignore_unused_variable_warning(b);
184 void const_constraints(const TT& b) {
186 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
187 a = b; // const required for argument to assignment
189 ignore_unused_variable_warning(c);
194 BOOST_concept(Convertible,(X)(Y))
196 BOOST_CONCEPT_USAGE(Convertible) {
198 ignore_unused_variable_warning(y);
204 // The C++ standard requirements for many concepts talk about return
205 // types that must be "convertible to bool". The problem with this
206 // requirement is that it leaves the door open for evil proxies that
207 // define things like operator|| with strange return types. Two
208 // possible solutions are:
209 // 1) require the return type to be exactly bool
210 // 2) stay with convertible to bool, and also
211 // specify stuff about all the logical operators.
212 // For now we just test for convertible to bool.
214 void require_boolean_expr(const TT& t) {
216 ignore_unused_variable_warning(x);
219 BOOST_concept(EqualityComparable,(TT))
221 BOOST_CONCEPT_USAGE(EqualityComparable) {
222 require_boolean_expr(a == b);
223 require_boolean_expr(a != b);
229 BOOST_concept(LessThanComparable,(TT))
231 BOOST_CONCEPT_USAGE(LessThanComparable) {
232 require_boolean_expr(a < b);
238 // This is equivalent to SGI STL's LessThanComparable.
239 BOOST_concept(Comparable,(TT))
241 BOOST_CONCEPT_USAGE(Comparable) {
242 require_boolean_expr(a < b);
243 require_boolean_expr(a > b);
244 require_boolean_expr(a <= b);
245 require_boolean_expr(a >= b);
251 #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
252 BOOST_concept(NAME, (First)(Second)) \
254 BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \
256 bool constraints_() { return a OP b; } \
261 #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
262 BOOST_concept(NAME, (Ret)(First)(Second)) \
264 BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \
266 Ret constraints_() { return a OP b; } \
271 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp);
272 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp);
273 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOp);
274 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOp);
275 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOp);
276 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOp);
278 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOp);
279 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOp);
280 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOp);
281 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOp);
282 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOp);
284 //===========================================================================
285 // Function Object Concepts
287 BOOST_concept(Generator,(Func)(Return))
289 BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); }
292 void test(boost::mpl::false_)
294 // Do we really want a reference here?
295 const Return& r = f();
296 ignore_unused_variable_warning(r);
299 void test(boost::mpl::true_)
307 BOOST_concept(UnaryFunction,(Func)(Return)(Arg))
309 BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); }
312 void test(boost::mpl::false_)
314 f(arg); // "priming the pump" this way keeps msvc6 happy (ICE)
316 ignore_unused_variable_warning(r);
319 void test(boost::mpl::true_)
328 BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second))
330 BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); }
332 void test(boost::mpl::false_)
335 Return r = f(first, second); // require operator()
339 void test(boost::mpl::true_)
349 BOOST_concept(UnaryPredicate,(Func)(Arg))
351 BOOST_CONCEPT_USAGE(UnaryPredicate) {
352 require_boolean_expr(f(arg)); // require operator() returning bool
359 BOOST_concept(BinaryPredicate,(Func)(First)(Second))
361 BOOST_CONCEPT_USAGE(BinaryPredicate) {
362 require_boolean_expr(f(a, b)); // require operator() returning bool
370 // use this when functor is used inside a container class like std::set
371 BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second))
372 : BinaryPredicate<Func, First, Second>
374 BOOST_CONCEPT_USAGE(Const_BinaryPredicate) {
375 const_constraints(f);
378 void const_constraints(const Func& fun) {
379 // operator() must be a const member function
380 require_boolean_expr(fun(a, b));
387 BOOST_concept(AdaptableGenerator,(Func)(Return))
388 : Generator<Func, typename Func::result_type>
390 typedef typename Func::result_type result_type;
392 BOOST_CONCEPT_USAGE(AdaptableGenerator)
394 BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
398 BOOST_concept(AdaptableUnaryFunction,(Func)(Return)(Arg))
399 : UnaryFunction<Func, typename Func::result_type, typename Func::argument_type>
401 typedef typename Func::argument_type argument_type;
402 typedef typename Func::result_type result_type;
404 ~AdaptableUnaryFunction()
406 BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
407 BOOST_CONCEPT_ASSERT((Convertible<Arg, argument_type>));
411 BOOST_concept(AdaptableBinaryFunction,(Func)(Return)(First)(Second))
414 , typename Func::result_type
415 , typename Func::first_argument_type
416 , typename Func::second_argument_type
419 typedef typename Func::first_argument_type first_argument_type;
420 typedef typename Func::second_argument_type second_argument_type;
421 typedef typename Func::result_type result_type;
423 ~AdaptableBinaryFunction()
425 BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
426 BOOST_CONCEPT_ASSERT((Convertible<First, first_argument_type>));
427 BOOST_CONCEPT_ASSERT((Convertible<Second, second_argument_type>));
431 BOOST_concept(AdaptablePredicate,(Func)(Arg))
432 : UnaryPredicate<Func, Arg>
433 , AdaptableUnaryFunction<Func, bool, Arg>
437 BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second))
438 : BinaryPredicate<Func, First, Second>
439 , AdaptableBinaryFunction<Func, bool, First, Second>
443 //===========================================================================
446 BOOST_concept(InputIterator,(TT))
448 , EqualityComparable<TT>
450 typedef typename boost::detail::iterator_traits<TT>::value_type value_type;
451 typedef typename boost::detail::iterator_traits<TT>::difference_type difference_type;
452 typedef typename boost::detail::iterator_traits<TT>::reference reference;
453 typedef typename boost::detail::iterator_traits<TT>::pointer pointer;
454 typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category;
456 BOOST_CONCEPT_USAGE(InputIterator)
458 BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
459 BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
462 (void)*i; // require dereference operator
463 ++j; // require preincrement operator
464 i++; // require postincrement operator
470 BOOST_concept(OutputIterator,(TT)(ValueT))
473 BOOST_CONCEPT_USAGE(OutputIterator) {
475 ++i; // require preincrement operator
476 i++; // require postincrement operator
477 *i++ = t; // require postincrement and assignment
484 BOOST_concept(ForwardIterator,(TT))
487 BOOST_CONCEPT_USAGE(ForwardIterator)
489 BOOST_CONCEPT_ASSERT((Convertible<
490 BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category
491 , std::forward_iterator_tag
494 typename InputIterator<TT>::reference r = *i;
495 ignore_unused_variable_warning(r);
502 BOOST_concept(Mutable_ForwardIterator,(TT))
503 : ForwardIterator<TT>
505 BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) {
506 *i++ = *i; // require postincrement and assignment
512 BOOST_concept(BidirectionalIterator,(TT))
513 : ForwardIterator<TT>
515 BOOST_CONCEPT_USAGE(BidirectionalIterator)
517 BOOST_CONCEPT_ASSERT((Convertible<
518 BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category
519 , std::bidirectional_iterator_tag
522 --i; // require predecrement operator
523 i--; // require postdecrement operator
529 BOOST_concept(Mutable_BidirectionalIterator,(TT))
530 : BidirectionalIterator<TT>
531 , Mutable_ForwardIterator<TT>
533 BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator)
535 *i-- = *i; // require postdecrement and assignment
541 BOOST_concept(RandomAccessIterator,(TT))
542 : BidirectionalIterator<TT>
545 BOOST_CONCEPT_USAGE(RandomAccessIterator)
547 BOOST_CONCEPT_ASSERT((Convertible<
548 BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category
549 , std::random_access_iterator_tag
552 i += n; // require assignment addition operator
553 i = i + n; i = n + i; // require addition with difference type
554 i -= n; // require assignment subtraction operator
555 i = i - n; // require subtraction with difference type
556 n = i - j; // require difference operator
557 (void)i[n]; // require element access operator
563 typename boost::detail::iterator_traits<TT>::difference_type n;
566 BOOST_concept(Mutable_RandomAccessIterator,(TT))
567 : RandomAccessIterator<TT>
568 , Mutable_BidirectionalIterator<TT>
570 BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator)
572 i[n] = *i; // require element access and assignment
576 typename boost::detail::iterator_traits<TT>::difference_type n;
579 //===========================================================================
582 BOOST_concept(Container,(C))
585 typedef typename C::value_type value_type;
586 typedef typename C::difference_type difference_type;
587 typedef typename C::size_type size_type;
588 typedef typename C::const_reference const_reference;
589 typedef typename C::const_pointer const_pointer;
590 typedef typename C::const_iterator const_iterator;
592 BOOST_CONCEPT_USAGE(Container)
594 BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>));
595 const_constraints(c);
599 void const_constraints(const C& cc) {
612 BOOST_concept(Mutable_Container,(C))
615 typedef typename C::reference reference;
616 typedef typename C::iterator iterator;
617 typedef typename C::pointer pointer;
619 BOOST_CONCEPT_USAGE(Mutable_Container)
621 BOOST_CONCEPT_ASSERT((
622 Assignable<typename Mutable_Container::value_type>));
624 BOOST_CONCEPT_ASSERT((InputIterator<iterator>));
636 BOOST_concept(ForwardContainer,(C))
639 BOOST_CONCEPT_USAGE(ForwardContainer)
641 BOOST_CONCEPT_ASSERT((
643 typename ForwardContainer::const_iterator
648 BOOST_concept(Mutable_ForwardContainer,(C))
649 : ForwardContainer<C>
650 , Mutable_Container<C>
652 BOOST_CONCEPT_USAGE(Mutable_ForwardContainer)
654 BOOST_CONCEPT_ASSERT((
655 Mutable_ForwardIterator<
656 typename Mutable_ForwardContainer::iterator
661 BOOST_concept(ReversibleContainer,(C))
662 : ForwardContainer<C>
665 C::const_reverse_iterator
666 const_reverse_iterator;
668 BOOST_CONCEPT_USAGE(ReversibleContainer)
670 BOOST_CONCEPT_ASSERT((
671 BidirectionalIterator<
672 typename ReversibleContainer::const_iterator>));
674 BOOST_CONCEPT_ASSERT((BidirectionalIterator<const_reverse_iterator>));
676 const_constraints(c);
679 void const_constraints(const C& cc)
681 const_reverse_iterator i = cc.rbegin();
687 BOOST_concept(Mutable_ReversibleContainer,(C))
688 : Mutable_ForwardContainer<C>
689 , ReversibleContainer<C>
691 typedef typename C::reverse_iterator reverse_iterator;
693 BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer)
695 typedef typename Mutable_ForwardContainer<C>::iterator iterator;
696 BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>));
697 BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<reverse_iterator>));
699 reverse_iterator i = c.rbegin();
706 BOOST_concept(RandomAccessContainer,(C))
707 : ReversibleContainer<C>
709 typedef typename C::size_type size_type;
710 typedef typename C::const_reference const_reference;
712 BOOST_CONCEPT_USAGE(RandomAccessContainer)
714 BOOST_CONCEPT_ASSERT((
715 RandomAccessIterator<
716 typename RandomAccessContainer::const_iterator
719 const_constraints(c);
722 void const_constraints(const C& cc)
724 const_reference r = cc[n];
725 ignore_unused_variable_warning(r);
732 BOOST_concept(Mutable_RandomAccessContainer,(C))
733 : Mutable_ReversibleContainer<C>
734 , RandomAccessContainer<C>
737 typedef Mutable_RandomAccessContainer self;
739 BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer)
741 BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>));
742 BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_iterator>));
744 typename self::reference r = c[i];
745 ignore_unused_variable_warning(r);
749 typename Mutable_ReversibleContainer<C>::size_type i;
753 // A Sequence is inherently mutable
754 BOOST_concept(Sequence,(S))
755 : Mutable_ForwardContainer<S>
756 // Matt Austern's book puts DefaultConstructible here, the C++
757 // standard places it in Container --JGS
758 // ... so why aren't we following the standard? --DWA
759 , DefaultConstructible<S>
761 BOOST_CONCEPT_USAGE(Sequence)
770 c.insert(p, first, last);
775 typename Sequence::reference r = c.front();
777 ignore_unused_variable_warning(c);
778 ignore_unused_variable_warning(c2);
779 ignore_unused_variable_warning(c3);
780 ignore_unused_variable_warning(r);
781 const_constraints(c);
784 void const_constraints(const S& c) {
785 typename Sequence::const_reference r = c.front();
786 ignore_unused_variable_warning(r);
789 typename S::value_type t;
790 typename S::size_type n;
791 typename S::value_type* first, *last;
792 typename S::iterator p, q;
795 BOOST_concept(FrontInsertionSequence,(S))
798 BOOST_CONCEPT_USAGE(FrontInsertionSequence)
805 typename S::value_type t;
808 BOOST_concept(BackInsertionSequence,(S))
811 BOOST_CONCEPT_USAGE(BackInsertionSequence)
815 typename BackInsertionSequence::reference r = c.back();
816 ignore_unused_variable_warning(r);
817 const_constraints(c);
820 void const_constraints(const S& cc) {
821 typename BackInsertionSequence::const_reference
823 ignore_unused_variable_warning(r);
826 typename S::value_type t;
829 BOOST_concept(AssociativeContainer,(C))
830 : ForwardContainer<C>
831 , DefaultConstructible<C>
833 typedef typename C::key_type key_type;
834 typedef typename C::key_compare key_compare;
835 typedef typename C::value_compare value_compare;
836 typedef typename C::iterator iterator;
838 BOOST_CONCEPT_USAGE(AssociativeContainer)
841 r = c.equal_range(k);
844 c.erase(r.first, r.second);
845 const_constraints(c);
846 BOOST_CONCEPT_ASSERT((BinaryPredicate<key_compare,key_type,key_type>));
848 typedef typename AssociativeContainer::value_type value_type_;
849 BOOST_CONCEPT_ASSERT((BinaryPredicate<value_compare,value_type_,value_type_>));
852 // Redundant with the base concept, but it helps below.
853 typedef typename C::const_iterator const_iterator;
855 void const_constraints(const C& cc)
859 cr = cc.equal_range(k);
864 std::pair<iterator,iterator> r;
866 std::pair<const_iterator,const_iterator> cr;
867 typename C::key_type k;
868 typename C::size_type n;
871 BOOST_concept(UniqueAssociativeContainer,(C))
872 : AssociativeContainer<C>
874 BOOST_CONCEPT_USAGE(UniqueAssociativeContainer)
878 pos_flag = c.insert(t);
879 c.insert(first, last);
881 ignore_unused_variable_warning(c);
884 std::pair<typename C::iterator, bool> pos_flag;
885 typename C::value_type t;
886 typename C::value_type* first, *last;
889 BOOST_concept(MultipleAssociativeContainer,(C))
890 : AssociativeContainer<C>
892 BOOST_CONCEPT_USAGE(MultipleAssociativeContainer)
897 c.insert(first, last);
899 ignore_unused_variable_warning(c);
900 ignore_unused_variable_warning(pos);
903 typename C::iterator pos;
904 typename C::value_type t;
905 typename C::value_type* first, *last;
908 BOOST_concept(SimpleAssociativeContainer,(C))
909 : AssociativeContainer<C>
911 BOOST_CONCEPT_USAGE(SimpleAssociativeContainer)
913 typedef typename C::key_type key_type;
914 typedef typename C::value_type value_type;
915 BOOST_MPL_ASSERT((boost::is_same<key_type,value_type>));
919 BOOST_concept(PairAssociativeContainer,(C))
920 : AssociativeContainer<C>
922 BOOST_CONCEPT_USAGE(PairAssociativeContainer)
924 typedef typename C::key_type key_type;
925 typedef typename C::value_type value_type;
926 typedef typename C::mapped_type mapped_type;
927 typedef std::pair<const key_type, mapped_type> required_value_type;
928 BOOST_MPL_ASSERT((boost::is_same<value_type,required_value_type>));
932 BOOST_concept(SortedAssociativeContainer,(C))
933 : AssociativeContainer<C>
934 , ReversibleContainer<C>
936 BOOST_CONCEPT_USAGE(SortedAssociativeContainer)
943 p = c.upper_bound(k);
944 p = c.lower_bound(k);
945 r = c.equal_range(k);
949 ignore_unused_variable_warning(c);
950 ignore_unused_variable_warning(c2);
951 ignore_unused_variable_warning(c3);
952 const_constraints(c);
955 void const_constraints(const C& c)
960 cp = c.upper_bound(k);
961 cp = c.lower_bound(k);
962 cr = c.equal_range(k);
966 typename C::key_compare kc;
967 typename C::value_compare vc;
968 typename C::value_type t;
969 typename C::key_type k;
970 typedef typename C::iterator iterator;
971 typedef typename C::const_iterator const_iterator;
973 typedef SortedAssociativeContainer self;
976 std::pair<typename self::iterator,typename self::iterator> r;
977 std::pair<typename self::const_iterator,typename self::const_iterator> cr;
978 typename C::value_type* first, *last;
981 // HashedAssociativeContainer
985 # include <boost/concept/detail/concept_undef.hpp>
987 #endif // BOOST_CONCEPT_CHECKS_HPP