// // (C) Copyright Jeremy Siek 2000. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Revision History: // 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) // 02 April 2001: Removed limits header altogether. (Jeremy Siek) // 01 April 2001: Modified to use new header. (JMaddock) // // See http://www.boost.org/libs/concept_check for documentation. #ifndef BOOST_CONCEPT_CHECKS_HPP #define BOOST_CONCEPT_CHECKS_HPP #include #include #include #include #include #include #include #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__BORLANDC__) #define BOOST_FPTR #else #define BOOST_FPTR & #endif namespace boost { /* "inline" is used for ignore_unused_variable_warning() and function_requires() to make sure there is no overhead with g++. */ template inline void ignore_unused_variable_warning(const T&) { } // the unused, defaulted parameter is a workaround for MSVC and Compaq C++ template inline void function_requires(mpl::identity* = 0) { #if !defined(NDEBUG) void (Concept::*x)() = BOOST_FPTR Concept::constraints; ignore_unused_variable_warning(x); #endif } #define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ typedef void (ns::concept ::* func##type_var##concept)(); \ template \ struct concept_checking_##type_var##concept { }; \ typedef concept_checking_##type_var##concept< \ BOOST_FPTR ns::concept::constraints> \ concept_checking_typedef_##type_var##concept #define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ typedef void (ns::concept ::* \ func##type_var1##type_var2##concept)(); \ template \ struct concept_checking_##type_var1##type_var2##concept { }; \ typedef concept_checking_##type_var1##type_var2##concept< \ BOOST_FPTR ns::concept::constraints> \ concept_checking_typedef_##type_var1##type_var2##concept #define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ typedef void (ns::concept ::* \ func##tv1##tv2##tv3##concept)(); \ template \ struct concept_checking_##tv1##tv2##tv3##concept { }; \ typedef concept_checking_##tv1##tv2##tv3##concept< \ BOOST_FPTR ns::concept::constraints> \ concept_checking_typedef_##tv1##tv2##tv3##concept #define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ typedef void (ns::concept ::* \ func##tv1##tv2##tv3##tv4##concept)(); \ template \ struct concept_checking_##tv1##tv2##tv3##tv4##concept { }; \ typedef concept_checking_##tv1##tv2##tv3##tv4##concept< \ BOOST_FPTR ns::concept::constraints> \ concept_checking_typedef_##tv1##tv2##tv3##tv4##concept // NOTE: The BOOST_CLASS_REQUIRES (with an 'S' at the end) is deprecated. // The BOOST_CLASS_REQUIRES macros use function pointers as // template parameters, which VC++ does not support. #if defined(BOOST_NO_FUNCTION_PTR_TEMPLATE_PARAMETERS) #define BOOST_CLASS_REQUIRES(type_var, concept) #define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept) #define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept) #define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept) #else #define BOOST_CLASS_REQUIRES(type_var, concept) \ typedef void (concept ::* func##type_var##concept)(); \ template \ struct concept_checking_##type_var##concept { }; \ typedef concept_checking_##type_var##concept< \ BOOST_FPTR concept ::constraints> \ concept_checking_typedef_##type_var##concept #define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept) \ typedef void (concept ::* func##type_var1##type_var2##concept)(); \ template \ struct concept_checking_##type_var1##type_var2##concept { }; \ typedef concept_checking_##type_var1##type_var2##concept< \ BOOST_FPTR concept ::constraints> \ concept_checking_typedef_##type_var1##type_var2##concept #define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept) \ typedef void (concept ::* func##type_var1##type_var2##type_var3##concept)(); \ template \ struct concept_checking_##type_var1##type_var2##type_var3##concept { }; \ typedef concept_checking_##type_var1##type_var2##type_var3##concept< \ BOOST_FPTR concept ::constraints> \ concept_checking_typedef_##type_var1##type_var2##type_var3##concept #define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept) \ typedef void (concept ::* func##type_var1##type_var2##type_var3##type_var4##concept)(); \ template \ struct concept_checking_##type_var1##type_var2##type_var3##type_var4##concept { }; \ typedef concept_checking_##type_var1##type_var2##type_var3##type_var4##concept< \ BOOST_FPTR concept ::constraints> \ concept_checking_typedef_##type_var1##type_var2##type_var3##type_var4##concept #endif #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct require_same { }; template struct require_same { typedef T type; }; #else // This version does not perform checking, but will not do any harm. template struct require_same { typedef T type; }; #endif template struct IntegerConcept { void constraints() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION x.error_type_must_be_an_integer_type(); #endif } T x; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template <> struct IntegerConcept { void constraints() {} }; template <> struct IntegerConcept { void constraints() {} }; template <> struct IntegerConcept { void constraints() {} }; template <> struct IntegerConcept { void constraints() {} }; template <> struct IntegerConcept { void constraints() {} }; template <> struct IntegerConcept { void constraints() {} }; // etc. #endif template struct SignedIntegerConcept { void constraints() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION x.error_type_must_be_a_signed_integer_type(); #endif } T x; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template <> struct SignedIntegerConcept { void constraints() {} }; template <> struct SignedIntegerConcept { void constraints() {} }; template <> struct SignedIntegerConcept { void constraints() {} }; # if defined(BOOST_HAS_LONG_LONG) template <> struct SignedIntegerConcept< ::boost::long_long_type> { void constraints() {} }; # endif // etc. #endif template struct UnsignedIntegerConcept { void constraints() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION x.error_type_must_be_an_unsigned_integer_type(); #endif } T x; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template <> struct UnsignedIntegerConcept { void constraints() {} }; template <> struct UnsignedIntegerConcept { void constraints() {} }; template <> struct UnsignedIntegerConcept { void constraints() {} }; // etc. #endif //=========================================================================== // Basic Concepts template struct DefaultConstructibleConcept { void constraints() { TT a; // require default constructor ignore_unused_variable_warning(a); } }; template struct AssignableConcept { void constraints() { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator #endif const_constraints(a); } void const_constraints(const TT& b) { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = b; // const required for argument to assignment #endif } TT a; }; template struct CopyConstructibleConcept { void constraints() { TT a(b); // require copy constructor TT* ptr = &a; // require address of operator const_constraints(a); ignore_unused_variable_warning(ptr); } void const_constraints(const TT& a) { TT c(a); // require const copy constructor const TT* ptr = &a; // require const address of operator ignore_unused_variable_warning(c); ignore_unused_variable_warning(ptr); } TT b; }; // The SGI STL version of Assignable requires copy constructor and operator= template struct SGIAssignableConcept { void constraints() { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator #endif const_constraints(a); ignore_unused_variable_warning(b); } void const_constraints(const TT& b) { TT c(b); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = b; // const required for argument to assignment #endif ignore_unused_variable_warning(c); } TT a; }; template struct ConvertibleConcept { void constraints() { Y y = x; ignore_unused_variable_warning(y); } X x; }; // The C++ standard requirements for many concepts talk about return // types that must be "convertible to bool". The problem with this // requirement is that it leaves the door open for evil proxies that // define things like operator|| with strange return types. Two // possible solutions are: // 1) require the return type to be exactly bool // 2) stay with convertible to bool, and also // specify stuff about all the logical operators. // For now we just test for convertible to bool. template void require_boolean_expr(const TT& t) { bool x = t; ignore_unused_variable_warning(x); } template struct EqualityComparableConcept { void constraints() { require_boolean_expr(a == b); require_boolean_expr(a != b); } TT a, b; }; template struct LessThanComparableConcept { void constraints() { require_boolean_expr(a < b); } TT a, b; }; // This is equivalent to SGI STL's LessThanComparable. template struct ComparableConcept { void constraints() { require_boolean_expr(a < b); require_boolean_expr(a > b); require_boolean_expr(a <= b); require_boolean_expr(a >= b); } TT a, b; }; #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ template \ struct NAME { \ void constraints() { (void)constraints_(); } \ bool constraints_() { \ return a OP b; \ } \ First a; \ Second b; \ } #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ template \ struct NAME { \ void constraints() { (void)constraints_(); } \ Ret constraints_() { \ return a OP b; \ } \ First a; \ Second b; \ } BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOpConcept); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOpConcept); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOpConcept); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOpConcept); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOpConcept); BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOpConcept); BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOpConcept); BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOpConcept); BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOpConcept); BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOpConcept); //=========================================================================== // Function Object Concepts template struct GeneratorConcept { void constraints() { const Return& r = f(); // require operator() member function ignore_unused_variable_warning(r); } Func f; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct GeneratorConcept { void constraints() { f(); // require operator() member function } Func f; }; #endif template struct UnaryFunctionConcept { // required in case any of our template args are const-qualified: UnaryFunctionConcept(); void constraints() { r = f(arg); // require operator() } Func f; Arg arg; Return r; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct UnaryFunctionConcept { void constraints() { f(arg); // require operator() } Func f; Arg arg; }; #endif template struct BinaryFunctionConcept { void constraints() { r = f(first, second); // require operator() } Func f; First first; Second second; Return r; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct BinaryFunctionConcept { void constraints() { f(first, second); // require operator() } Func f; First first; Second second; }; #endif template struct UnaryPredicateConcept { void constraints() { require_boolean_expr(f(arg)); // require operator() returning bool } Func f; Arg arg; }; template struct BinaryPredicateConcept { void constraints() { require_boolean_expr(f(a, b)); // require operator() returning bool } Func f; First a; Second b; }; // use this when functor is used inside a container class like std::set template struct Const_BinaryPredicateConcept { void constraints() { const_constraints(f); } void const_constraints(const Func& fun) { function_requires >(); // operator() must be a const member function require_boolean_expr(fun(a, b)); } Func f; First a; Second b; }; template struct AdaptableGeneratorConcept { void constraints() { typedef typename Func::result_type result_type; BOOST_STATIC_ASSERT((is_convertible::value)); function_requires< GeneratorConcept >(); } }; template struct AdaptableUnaryFunctionConcept { void constraints() { typedef typename Func::argument_type argument_type; typedef typename Func::result_type result_type; BOOST_STATIC_ASSERT((is_convertible::value)); BOOST_STATIC_ASSERT((is_convertible::value)); function_requires< UnaryFunctionConcept >(); } }; template struct AdaptableBinaryFunctionConcept { void constraints() { typedef typename Func::first_argument_type first_argument_type; typedef typename Func::second_argument_type second_argument_type; typedef typename Func::result_type result_type; BOOST_STATIC_ASSERT((is_convertible::value)); BOOST_STATIC_ASSERT((is_convertible::value)); BOOST_STATIC_ASSERT((is_convertible::value)); function_requires< BinaryFunctionConcept >(); } }; template struct AdaptablePredicateConcept { void constraints() { function_requires< UnaryPredicateConcept >(); function_requires< AdaptableUnaryFunctionConcept >(); } }; template struct AdaptableBinaryPredicateConcept { void constraints() { function_requires< BinaryPredicateConcept >(); function_requires< AdaptableBinaryFunctionConcept >(); } }; //=========================================================================== // Iterator Concepts template struct InputIteratorConcept { void constraints() { function_requires< AssignableConcept >(); function_requires< EqualityComparableConcept >(); TT j(i); (void)*i; // require dereference operator #ifndef BOOST_NO_STD_ITERATOR_TRAITS // require iterator_traits typedef's typedef typename std::iterator_traits::difference_type D; // Hmm, the following is a bit fragile //function_requires< SignedIntegerConcept >(); typedef typename std::iterator_traits::reference R; typedef typename std::iterator_traits::pointer P; typedef typename std::iterator_traits::iterator_category C; function_requires< ConvertibleConcept >(); #endif ++j; // require preincrement operator i++; // require postincrement operator } TT i; }; template struct OutputIteratorConcept { void constraints() { function_requires< AssignableConcept >(); ++i; // require preincrement operator i++; // require postincrement operator *i++ = t; // require postincrement and assignment } TT i, j; ValueT t; }; template struct ForwardIteratorConcept { void constraints() { function_requires< InputIteratorConcept >(); #ifndef BOOST_NO_STD_ITERATOR_TRAITS typedef typename std::iterator_traits::iterator_category C; function_requires< ConvertibleConcept >(); typedef typename std::iterator_traits::reference reference; reference r = *i; ignore_unused_variable_warning(r); #endif } TT i; }; template struct Mutable_ForwardIteratorConcept { void constraints() { function_requires< ForwardIteratorConcept >(); *i++ = *i; // require postincrement and assignment } TT i; }; template struct BidirectionalIteratorConcept { void constraints() { function_requires< ForwardIteratorConcept >(); #ifndef BOOST_NO_STD_ITERATOR_TRAITS typedef typename std::iterator_traits::iterator_category C; function_requires< ConvertibleConcept >(); #endif --i; // require predecrement operator i--; // require postdecrement operator } TT i; }; template struct Mutable_BidirectionalIteratorConcept { void constraints() { function_requires< BidirectionalIteratorConcept >(); function_requires< Mutable_ForwardIteratorConcept >(); *i-- = *i; // require postdecrement and assignment } TT i; }; template struct RandomAccessIteratorConcept { void constraints() { function_requires< BidirectionalIteratorConcept >(); function_requires< ComparableConcept >(); #ifndef BOOST_NO_STD_ITERATOR_TRAITS typedef typename std::iterator_traits::iterator_category C; function_requires< ConvertibleConcept< C, std::random_access_iterator_tag> >(); typedef typename std::iterator_traits::reference R; #endif i += n; // require assignment addition operator i = i + n; i = n + i; // require addition with difference type i -= n; // require assignment subtraction operator i = i - n; // require subtraction with difference type n = i - j; // require difference operator (void)i[n]; // require element access operator } TT a, b; TT i, j; #ifndef BOOST_NO_STD_ITERATOR_TRAITS typename std::iterator_traits::difference_type n; #else std::ptrdiff_t n; #endif }; template struct Mutable_RandomAccessIteratorConcept { void constraints() { function_requires< RandomAccessIteratorConcept >(); function_requires< Mutable_BidirectionalIteratorConcept >(); i[n] = *i; // require element access and assignment } TT i; #ifndef BOOST_NO_STD_ITERATOR_TRAITS typename std::iterator_traits::difference_type n; #else std::ptrdiff_t n; #endif }; //=========================================================================== // Container Concepts template struct ContainerConcept { typedef typename Container::value_type value_type; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef typename Container::const_reference const_reference; typedef typename Container::const_pointer const_pointer; typedef typename Container::const_iterator const_iterator; void constraints() { function_requires< InputIteratorConcept >(); function_requires< AssignableConcept >(); const_constraints(c); } void const_constraints(const Container& cc) { i = cc.begin(); i = cc.end(); n = cc.size(); n = cc.max_size(); b = cc.empty(); } Container c; bool b; const_iterator i; size_type n; }; template struct Mutable_ContainerConcept { typedef typename Container::value_type value_type; typedef typename Container::reference reference; typedef typename Container::iterator iterator; typedef typename Container::pointer pointer; void constraints() { function_requires< ContainerConcept >(); function_requires< AssignableConcept >(); function_requires< InputIteratorConcept >(); i = c.begin(); i = c.end(); c.swap(c2); } iterator i; Container c, c2; }; template struct ForwardContainerConcept { void constraints() { function_requires< ContainerConcept >(); typedef typename ForwardContainer::const_iterator const_iterator; function_requires< ForwardIteratorConcept >(); } }; template struct Mutable_ForwardContainerConcept { void constraints() { function_requires< ForwardContainerConcept >(); function_requires< Mutable_ContainerConcept >(); typedef typename ForwardContainer::iterator iterator; function_requires< Mutable_ForwardIteratorConcept >(); } }; template struct ReversibleContainerConcept { typedef typename ReversibleContainer::const_iterator const_iterator; typedef typename ReversibleContainer::const_reverse_iterator const_reverse_iterator; void constraints() { function_requires< ForwardContainerConcept >(); function_requires< BidirectionalIteratorConcept >(); function_requires< BidirectionalIteratorConcept >(); const_constraints(c); } void const_constraints(const ReversibleContainer& cc) { const_reverse_iterator i = cc.rbegin(); i = cc.rend(); } ReversibleContainer c; }; template struct Mutable_ReversibleContainerConcept { typedef typename ReversibleContainer::iterator iterator; typedef typename ReversibleContainer::reverse_iterator reverse_iterator; void constraints() { function_requires< ReversibleContainerConcept >(); function_requires< Mutable_ForwardContainerConcept >(); function_requires< Mutable_BidirectionalIteratorConcept >(); function_requires< Mutable_BidirectionalIteratorConcept >(); reverse_iterator i = c.rbegin(); i = c.rend(); } ReversibleContainer c; }; template struct RandomAccessContainerConcept { typedef typename RandomAccessContainer::size_type size_type; typedef typename RandomAccessContainer::const_reference const_reference; typedef typename RandomAccessContainer::const_iterator const_iterator; typedef typename RandomAccessContainer::const_reverse_iterator const_reverse_iterator; void constraints() { function_requires< ReversibleContainerConcept >(); function_requires< RandomAccessIteratorConcept >(); function_requires< RandomAccessIteratorConcept >(); const_constraints(c); } void const_constraints(const RandomAccessContainer& cc) { const_reference r = cc[n]; ignore_unused_variable_warning(r); } RandomAccessContainer c; size_type n; }; template struct Mutable_RandomAccessContainerConcept { typedef typename RandomAccessContainer::size_type size_type; typedef typename RandomAccessContainer::reference reference; typedef typename RandomAccessContainer::iterator iterator; typedef typename RandomAccessContainer::reverse_iterator reverse_iterator; void constraints() { function_requires< RandomAccessContainerConcept >(); function_requires< Mutable_ReversibleContainerConcept >(); function_requires< Mutable_RandomAccessIteratorConcept >(); function_requires< Mutable_RandomAccessIteratorConcept >(); reference r = c[i]; ignore_unused_variable_warning(r); } size_type i; RandomAccessContainer c; }; // A Sequence is inherently mutable template struct SequenceConcept { typedef typename Sequence::reference reference; typedef typename Sequence::const_reference const_reference; void constraints() { // Matt Austern's book puts DefaultConstructible here, the C++ // standard places it in Container // function_requires< DefaultConstructible >(); function_requires< Mutable_ForwardContainerConcept >(); function_requires< DefaultConstructibleConcept >(); Sequence c(n), c2(n, t), c3(first, last); c.insert(p, t); c.insert(p, n, t); c.insert(p, first, last); c.erase(p); c.erase(p, q); reference r = c.front(); ignore_unused_variable_warning(c); ignore_unused_variable_warning(c2); ignore_unused_variable_warning(c3); ignore_unused_variable_warning(r); const_constraints(c); } void const_constraints(const Sequence& c) { const_reference r = c.front(); ignore_unused_variable_warning(r); } typename Sequence::value_type t; typename Sequence::size_type n; typename Sequence::value_type* first, *last; typename Sequence::iterator p, q; }; template struct FrontInsertionSequenceConcept { void constraints() { function_requires< SequenceConcept >(); c.push_front(t); c.pop_front(); } FrontInsertionSequence c; typename FrontInsertionSequence::value_type t; }; template struct BackInsertionSequenceConcept { typedef typename BackInsertionSequence::reference reference; typedef typename BackInsertionSequence::const_reference const_reference; void constraints() { function_requires< SequenceConcept >(); c.push_back(t); c.pop_back(); reference r = c.back(); ignore_unused_variable_warning(r); } void const_constraints(const BackInsertionSequence& cc) { const_reference r = cc.back(); ignore_unused_variable_warning(r); }; BackInsertionSequence c; typename BackInsertionSequence::value_type t; }; template struct AssociativeContainerConcept { void constraints() { function_requires< ForwardContainerConcept >(); function_requires< DefaultConstructibleConcept >(); i = c.find(k); r = c.equal_range(k); c.erase(k); c.erase(i); c.erase(r.first, r.second); const_constraints(c); } void const_constraints(const AssociativeContainer& cc) { ci = cc.find(k); n = cc.count(k); cr = cc.equal_range(k); } typedef typename AssociativeContainer::iterator iterator; typedef typename AssociativeContainer::const_iterator const_iterator; AssociativeContainer c; iterator i; std::pair r; const_iterator ci; std::pair cr; typename AssociativeContainer::key_type k; typename AssociativeContainer::size_type n; }; template struct UniqueAssociativeContainerConcept { void constraints() { function_requires< AssociativeContainerConcept >(); UniqueAssociativeContainer c(first, last); pos_flag = c.insert(t); c.insert(first, last); ignore_unused_variable_warning(c); } std::pair pos_flag; typename UniqueAssociativeContainer::value_type t; typename UniqueAssociativeContainer::value_type* first, *last; }; template struct MultipleAssociativeContainerConcept { void constraints() { function_requires< AssociativeContainerConcept >(); MultipleAssociativeContainer c(first, last); pos = c.insert(t); c.insert(first, last); ignore_unused_variable_warning(c); ignore_unused_variable_warning(pos); } typename MultipleAssociativeContainer::iterator pos; typename MultipleAssociativeContainer::value_type t; typename MultipleAssociativeContainer::value_type* first, *last; }; template struct SimpleAssociativeContainerConcept { void constraints() { function_requires< AssociativeContainerConcept >(); typedef typename SimpleAssociativeContainer::key_type key_type; typedef typename SimpleAssociativeContainer::value_type value_type; typedef typename require_same::type req; } }; template struct PairAssociativeContainerConcept { void constraints() { function_requires< AssociativeContainerConcept >(); typedef typename SimpleAssociativeContainer::key_type key_type; typedef typename SimpleAssociativeContainer::value_type value_type; typedef typename SimpleAssociativeContainer::mapped_type mapped_type; typedef std::pair required_value_type; typedef typename require_same::type req; } }; template struct SortedAssociativeContainerConcept { void constraints() { function_requires< AssociativeContainerConcept >(); function_requires< ReversibleContainerConcept >(); SortedAssociativeContainer c(kc), c2(first, last), c3(first, last, kc); p = c.upper_bound(k); p = c.lower_bound(k); r = c.equal_range(k); c.insert(p, t); ignore_unused_variable_warning(c); ignore_unused_variable_warning(c2); ignore_unused_variable_warning(c3); } void const_constraints(const SortedAssociativeContainer& c) { kc = c.key_comp(); vc = c.value_comp(); cp = c.upper_bound(k); cp = c.lower_bound(k); cr = c.equal_range(k); } typename SortedAssociativeContainer::key_compare kc; typename SortedAssociativeContainer::value_compare vc; typename SortedAssociativeContainer::value_type t; typename SortedAssociativeContainer::key_type k; typedef typename SortedAssociativeContainer::iterator iterator; typedef typename SortedAssociativeContainer::const_iterator const_iterator; iterator p; const_iterator cp; std::pair r; std::pair cr; typename SortedAssociativeContainer::value_type* first, *last; }; // HashedAssociativeContainer } // namespace boost #endif // BOOST_CONCEPT_CHECKS_HPP