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