ossrv_pub/boost_apis/boost/concept_check.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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