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