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