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