code:
// Boost.Range library
//
//  Copyright Neil Groves & Thorsten Ottosen & Pavol Droba 2003-2004.
//  Use, modification and distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//
// Credits:
// 'michel' reported Trac 9072 which included a patch for allowing references
// to function types.
//
#ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED
#define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED

#include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate.
#include <boost/detail/workaround.hpp>

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
    #pragma warning( push )
    #pragma warning( disable : 4996 )
#endif

#include <boost/assert.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_abstract.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/range/algorithm/equal.hpp>
#include <boost/range/detail/safe_bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <iterator>
#include <algorithm>
#include <cstddef>

/*! \file
    Defines the \c iterator_class and related functions.
    \c iterator_range is a simple wrapper of iterator pair idiom. It provides
    a rich subset of Container interface.
*/

namespace boost
{
    namespace iterator_range_detail
    {
        //
        // The functions adl_begin and adl_end are implemented in a separate
        // class for gcc-2.9x
        //
        template<class IteratorT>
        struct iterator_range_impl {
            template< class ForwardRange >
            static IteratorT adl_begin( ForwardRange& r )
            {
                return IteratorT( boost::begin( r ) );
            }

            template< class ForwardRange >
            static IteratorT adl_end( ForwardRange& r )
            {
                return IteratorT( boost::end( r ) );
            }
        };

        template< class Left, class Right >
        inline bool less_than( const Left& l, const Right& r )
        {
            return std::lexicographical_compare( boost::begin(l),
                                                 boost::end(l),
                                                 boost::begin(r),
                                                 boost::end(r) );
        }

        template< class Left, class Right >
        inline bool greater_than( const Left& l, const Right& r )
        {
            return iterator_range_detail::less_than(r,l);
        }

        template< class Left, class Right >
        inline bool less_or_equal_than( const Left& l, const Right& r )
        {
            return !iterator_range_detail::less_than(r,l);
        }

        template< class Left, class Right >
        inline bool greater_or_equal_than( const Left& l, const Right& r )
        {
            return !iterator_range_detail::less_than(l,r);
        }

        // This version is maintained since it is used in other boost libraries
        // such as Boost.Assign
        template< class Left, class Right >
        inline bool equal(const Left& l, const Right& r)
        {
            return boost::equal(l, r);
        }

struct range_tag
{
};

struct const_range_tag
{
};

struct iterator_range_tag
{
};

typedef char (&incrementable_t)[1];
typedef char (&bidirectional_t)[2];
typedef char (&random_access_t)[3];

incrementable_t test_traversal_tag(boost::incrementable_traversal_tag);
bidirectional_t test_traversal_tag(boost::bidirectional_traversal_tag);
random_access_t test_traversal_tag(boost::random_access_traversal_tag);

template<std::size_t S>
struct pure_iterator_traversal_impl
{
    typedef boost::incrementable_traversal_tag type;
};

template<>
struct pure_iterator_traversal_impl<sizeof(bidirectional_t)>
{
    typedef boost::bidirectional_traversal_tag type;
};

template<>
struct pure_iterator_traversal_impl<sizeof(random_access_t)>
{
    typedef boost::random_access_traversal_tag type;
};

template<typename IteratorT>
struct pure_iterator_traversal
{
    typedef
        BOOST_DEDUCED_TYPENAME iterator_traversal<IteratorT>::type
    traversal_t;
    BOOST_STATIC_CONSTANT(
        std::size_t,
        traversal_i = sizeof(iterator_range_detail::test_traversal_tag((traversal_t())))
    );
    typedef
        BOOST_DEDUCED_TYPENAME pure_iterator_traversal_impl<traversal_i>::type
    type;
};

template<class IteratorT, class TraversalTag>
class iterator_range_base
    : public iterator_range_tag
{
    typedef range_detail::safe_bool<
                IteratorT iterator_range_base<IteratorT, TraversalTag>::*
    > safe_bool_t;

    typedef iterator_range_base<IteratorT, TraversalTag> type;

protected:
    typedef iterator_range_impl<IteratorT> impl;

public:
    typedef BOOST_DEDUCED_TYPENAME
        safe_bool_t::unspecified_bool_type unspecified_bool_type;

    typedef BOOST_DEDUCED_TYPENAME
        iterator_value<IteratorT>::type value_type;

    typedef BOOST_DEDUCED_TYPENAME
        iterator_difference<IteratorT>::type difference_type;

    typedef std::size_t size_type; // note: must be unsigned

    // Needed because value-type is the same for
    // const and non-const iterators
    typedef BOOST_DEDUCED_TYPENAME
                iterator_reference<IteratorT>::type reference;

    //! const_iterator type
    /*!
        There is no distinction between const_iterator and iterator.
        These typedefs are provides to fulfill container interface
    */
    typedef IteratorT const_iterator;
    //! iterator type
    typedef IteratorT iterator;

protected:
    iterator_range_base()
        : m_Begin()
        , m_End()
    {
    }

    template<class Iterator>
    iterator_range_base(Iterator Begin, Iterator End)
        : m_Begin(Begin)
        , m_End(End)
    {
    }

public:
    IteratorT begin() const
    {
        return m_Begin;
    }

    IteratorT end() const
    {
        return m_End;
    }

    bool empty() const
    {
        return m_Begin == m_End;
    }

    operator unspecified_bool_type() const
    {
        return safe_bool_t::to_unspecified_bool(
                    m_Begin != m_End, &iterator_range_base::m_Begin);
    }

    bool operator!() const
    {
        return empty();
    }

    bool equal(const iterator_range_base& r) const
    {
        return m_Begin == r.m_Begin && m_End == r.m_End;
    }

   reference front() const
   {
       BOOST_ASSERT(!empty());
       return *m_Begin;
   }

   void drop_front()
   {
       BOOST_ASSERT(!empty());
       ++m_Begin;
   }

   void drop_front(difference_type n)
   {
       BOOST_ASSERT(n >= difference_type());
       std::advance(this->m_Begin, n);
   }

   // Deprecated
   void pop_front() { drop_front(); }

protected:
    template<class Iterator>
    void assign(Iterator first, Iterator last)
    {
        m_Begin = first;
        m_End = last;
    }

    template<class SinglePassRange>
    void assign(const SinglePassRange& r)
    {
        m_Begin = impl::adl_begin(r);
        m_End = impl::adl_end(r);
    }

    template<class SinglePassRange>
    void assign(SinglePassRange& r)
    {
        m_Begin = impl::adl_begin(r);
        m_End = impl::adl_end(r);
    }

    IteratorT m_Begin;
    IteratorT m_End;
};

template<class IteratorT>
class iterator_range_base<IteratorT, bidirectional_traversal_tag>
        : public iterator_range_base<IteratorT, incrementable_traversal_tag>
{
    typedef iterator_range_base<IteratorT, incrementable_traversal_tag> base_type;

protected:
    iterator_range_base()
    {
    }

    template<class Iterator>
    iterator_range_base(Iterator first, Iterator last)
        : base_type(first, last)
    {
    }

public:
    typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type;
    typedef BOOST_DEDUCED_TYPENAME base_type::reference reference;

    reference back() const
    {
        BOOST_ASSERT(!this->empty());
        return *boost::prior(this->m_End);
    }

    void drop_back()
    {
        BOOST_ASSERT(!this->empty());
        --this->m_End;
    }

    void drop_back(difference_type n)
    {
        BOOST_ASSERT(n >= difference_type());
        std::advance(this->m_End, -n);
    }

    // Deprecated
    void pop_back() { drop_back(); }
};

template<class IteratorT>
class iterator_range_base<IteratorT, random_access_traversal_tag>
        : public iterator_range_base<IteratorT, bidirectional_traversal_tag>
{
    typedef iterator_range_base<
                IteratorT, bidirectional_traversal_tag> base_type;

public:
    typedef BOOST_DEDUCED_TYPENAME
        boost::mpl::if_<
            boost::mpl::or_<
                boost::is_abstract<
                    BOOST_DEDUCED_TYPENAME base_type::value_type
                >,
                boost::is_array<
                    BOOST_DEDUCED_TYPENAME base_type::value_type
                >,
                boost::is_function<
                    BOOST_DEDUCED_TYPENAME base_type::value_type
                >
            >,
            BOOST_DEDUCED_TYPENAME base_type::reference,
            BOOST_DEDUCED_TYPENAME base_type::value_type
        >::type abstract_value_type;

    // Rationale:
    // typedef these here to reduce verbiage in the implementation of this
    // type.
    typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type;
    typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type;
    typedef BOOST_DEDUCED_TYPENAME base_type::reference reference;

protected:
    iterator_range_base()
    {
    }

    template<class Iterator>
    iterator_range_base(Iterator first, Iterator last)
        : base_type(first, last)
    {
    }

public:
    reference operator[](difference_type at) const
    {
        BOOST_ASSERT(at >= 0);
        BOOST_ASSERT(static_cast<typename base_type::size_type>(at) < size());
        return this->m_Begin[at];
    }

    //
    // When storing transform iterators, operator[]()
    // fails because it returns by reference. Therefore
    // operator()() is provided for these cases.
    //
    abstract_value_type operator()(difference_type at) const
    {
        BOOST_ASSERT(at >= 0);
        BOOST_ASSERT(static_cast<typename base_type::size_type>(at) < size());
        return this->m_Begin[at];
    }

    BOOST_DEDUCED_TYPENAME base_type::size_type size() const
    {
        return this->m_End - this->m_Begin;
    }
};

    }

//  iterator range template class -----------------------------------------//

        //! iterator_range class
        /*!
            An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
            An iterator_range can be passed to an algorithm which requires a sequence as an input.
            For example, the \c toupper() function may be used most frequently on strings,
            but can also be used on iterator_ranges:

            \code
                boost::tolower( find( s, "UPPERCASE STRING" ) );
            \endcode

            Many algorithms working with sequences take a pair of iterators,
            delimiting a working range, as an arguments. The \c iterator_range class is an
            encapsulation of a range identified by a pair of iterators.
            It provides a collection interface,
            so it is possible to pass an instance to an algorithm requiring a collection as an input.
        */
        template<class IteratorT>
        class iterator_range
            : public iterator_range_detail::iterator_range_base<
                    IteratorT,
                    BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal<IteratorT>::type
                >
        {
            typedef iterator_range_detail::iterator_range_base<
                    IteratorT,
                    BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal<IteratorT>::type
            > base_type;

            template<class Source>
            struct is_compatible_range_
              : is_convertible<
                    BOOST_DEDUCED_TYPENAME mpl::eval_if<
                        has_range_iterator<Source>,
                        range_iterator<Source>,
                        mpl::identity<void>
                    >::type,
                    BOOST_DEDUCED_TYPENAME base_type::iterator
                >
            {
            };

            template<class Source>
            struct is_compatible_range
                : mpl::and_<
                    mpl::not_<
                        is_convertible<
                            Source,
                            BOOST_DEDUCED_TYPENAME base_type::iterator
                        >
                    >,
                    is_compatible_range_<Source>
                >
            {
            };

        protected:
            typedef iterator_range_detail::iterator_range_impl<IteratorT> impl;

        public:
            typedef iterator_range<IteratorT> type;

            iterator_range()
            {
            }

            template<class Iterator>
            iterator_range(Iterator first, Iterator last)
                : base_type(first, last)
            {
            }

            template<class SinglePassRange>
            iterator_range(
                const SinglePassRange& r,
                BOOST_DEDUCED_TYPENAME ::boost::enable_if<
                    is_compatible_range<const SinglePassRange>
                >::type* = 0
            )
                : base_type(impl::adl_begin(r), impl::adl_end(r))
            {
            }

            template<class SinglePassRange>
            iterator_range(
                SinglePassRange& r,
                BOOST_DEDUCED_TYPENAME ::boost::enable_if<
                    is_compatible_range<SinglePassRange>
                >::type* = 0
            )
                : base_type(impl::adl_begin(r), impl::adl_end(r))
            {
            }

            template<class SinglePassRange>
            iterator_range(const SinglePassRange& r,
                           iterator_range_detail::const_range_tag)
                : base_type(impl::adl_begin(r), impl::adl_end(r))
            {
            }

            template<class SinglePassRange>
            iterator_range(SinglePassRange& r,
                           iterator_range_detail::range_tag)
                : base_type(impl::adl_begin(r), impl::adl_end(r))
            {
            }

            template<class Iterator>
            iterator_range& operator=(const iterator_range<Iterator>& other)
            {
                this->assign(other.begin(), other.end());
                return *this;
            }

            template<class Iterator>
            iterator_range& operator=(iterator_range<Iterator>& other)
            {
                this->assign(other.begin(), other.end());
                return *this;
            }

            template<class SinglePassRange>
            iterator_range& operator=(SinglePassRange& r)
            {
                this->assign(r);
                return *this;
            }

            template<class SinglePassRange>
            iterator_range& operator=(const SinglePassRange& r)
            {
                this->assign(r);
                return *this;
            }

            iterator_range& advance_begin(
                BOOST_DEDUCED_TYPENAME base_type::difference_type n)
            {
                std::advance(this->m_Begin, n);
                return *this;
            }

            iterator_range& advance_end(
                BOOST_DEDUCED_TYPENAME base_type::difference_type n)
            {
                std::advance(this->m_End, n);
                return *this;
            }

        protected:
            //
            // Allow subclasses an easy way to access the
            // base type
            //
            typedef iterator_range iterator_range_;
        };

//  iterator range free-standing operators ---------------------------//

        /////////////////////////////////////////////////////////////////////
        // comparison operators
        /////////////////////////////////////////////////////////////////////

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator==( const ForwardRange& l, const iterator_range<IteratorT>& r )
        {
            return boost::equal( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator!=( const ForwardRange& l, const iterator_range<IteratorT>& r )
        {
            return !boost::equal( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator<( const ForwardRange& l, const iterator_range<IteratorT>& r )
        {
            return iterator_range_detail::less_than( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator<=( const ForwardRange& l, const iterator_range<IteratorT>& r )
        {
            return iterator_range_detail::less_or_equal_than( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator>( const ForwardRange& l, const iterator_range<IteratorT>& r )
        {
            return iterator_range_detail::greater_than( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator>=( const ForwardRange& l, const iterator_range<IteratorT>& r )
        {
            return iterator_range_detail::greater_or_equal_than( l, r );
        }

#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
#else
        template< class Iterator1T, class Iterator2T >
        inline bool
        operator==( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
        {
            return boost::equal( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator==( const iterator_range<IteratorT>& l, const ForwardRange& r )
        {
            return boost::equal( l, r );
        }

        template< class Iterator1T, class Iterator2T >
        inline bool
        operator!=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
        {
            return !boost::equal( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator!=( const iterator_range<IteratorT>& l, const ForwardRange& r )
        {
            return !boost::equal( l, r );
        }

        template< class Iterator1T, class Iterator2T >
        inline bool
        operator<( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
        {
            return iterator_range_detail::less_than( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator<( const iterator_range<IteratorT>& l, const ForwardRange& r )
        {
            return iterator_range_detail::less_than( l, r );
        }

        template< class Iterator1T, class Iterator2T >
        inline bool
        operator<=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
        {
            return iterator_range_detail::less_or_equal_than( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator<=( const iterator_range<IteratorT>& l, const ForwardRange& r )
        {
            return iterator_range_detail::less_or_equal_than( l, r );
        }

        template< class Iterator1T, class Iterator2T >
        inline bool
        operator>( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
        {
            return iterator_range_detail::greater_than( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator>( const iterator_range<IteratorT>& l, const ForwardRange& r )
        {
            return iterator_range_detail::greater_than( l, r );
        }

        template< class Iterator1T, class Iterator2T >
        inline bool
        operator>=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
        {
            return iterator_range_detail::greater_or_equal_than( l, r );
        }

        template< class IteratorT, class ForwardRange >
        inline BOOST_DEDUCED_TYPENAME boost::enable_if<
            mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
            bool
        >::type
        operator>=( const iterator_range<IteratorT>& l, const ForwardRange& r )
        {
            return iterator_range_detail::greater_or_equal_than( l, r );
        }

#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING

//  iterator range utilities -----------------------------------------//

        //! iterator_range construct helper
        /*!
            Construct an \c iterator_range from a pair of iterators

            \param Begin A begin iterator
            \param End An end iterator
            \return iterator_range object
        */
        template< typename IteratorT >
        inline iterator_range< IteratorT >
        make_iterator_range( IteratorT Begin, IteratorT End )
        {
            return iterator_range<IteratorT>( Begin, End );
        }

        template<typename IteratorT, typename IntegerT>
        inline iterator_range<IteratorT>
        make_iterator_range_n(IteratorT first, IntegerT n)
        {
            return iterator_range<IteratorT>(first, boost::next(first, n));
        }

#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING

        template< typename Range >
        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
        make_iterator_range( Range& r )
        {
            return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
                ( boost::begin( r ), boost::end( r ) );
        }

#else
        //! iterator_range construct helper
        /*!
            Construct an \c iterator_range from a \c Range containing the begin
            and end iterators.
        */
        template< class ForwardRange >
        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
        make_iterator_range( ForwardRange& r )
        {
           return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
                ( r, iterator_range_detail::range_tag() );
        }

        template< class ForwardRange >
        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
        make_iterator_range( const ForwardRange& r )
        {
           return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
                ( r, iterator_range_detail::const_range_tag() );
        }

#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING

        namespace iterator_range_detail
        {
            template< class Range >
            inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
            make_range_impl( Range& r,
                             BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
                             BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
            {
                //
                // Not worth the effort
                //
                //if( advance_begin == 0 && advance_end == 0 )
                //    return make_iterator_range( r );
                //

                BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
                    new_begin = boost::begin( r ),
                    new_end   = boost::end( r );
                std::advance( new_begin, advance_begin );
                std::advance( new_end, advance_end );
                return make_iterator_range( new_begin, new_end );
            }
        }

#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING

        template< class Range >
        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
        make_iterator_range( Range& r,
                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
        {
            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
        }

#else

        template< class Range >
        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
        make_iterator_range( Range& r,
                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
        {
            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
        }

        template< class Range >
        inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type >
        make_iterator_range( const Range& r,
                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
                    BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
        {
            return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
        }

#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING

        //! copy a range into a sequence
        /*!
            Construct a new sequence of the specified type from the elements
            in the given range

            \param Range An input range
            \return New sequence
        */
        template< typename SeqT, typename Range >
        inline SeqT copy_range( const Range& r )
        {
            return SeqT( boost::begin( r ), boost::end( r ) );
        }

} // namespace 'boost'

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
    #pragma warning( pop )
#endif

#endif


code:
// Boost.Range library
//
//  Copyright Neil Groves 2014
//  Use, modification and distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/iterator_range_core.hpp>
#include <boost/functional/hash.hpp>

namespace boost
{

template<class T>
std::size_t hash_value(const iterator_range<T>& rng)
{
    return boost::hash_range(rng.begin(), rng.end());
}

} // namespace boost

license: mit


code:
// Boost.Range library
//
//  Copyright Neil Groves 2009.
//  Use, modification and distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_ITERATOR_RANGE_IO_HPP_INCLUDED
#define BOOST_RANGE_ITERATOR_RANGE_IO_HPP_INCLUDED

#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
    #pragma warning( push )
    #pragma warning( disable : 4996 )
#endif

// From boost/dynamic_bitset.hpp; thanks to Matthias Troyer for Cray X1 patch.
#ifndef BOOST_OLD_IOSTREAMS
# if defined(__STL_CONFIG_H) && \
    !defined (__STL_USE_NEW_IOSTREAMS) && !defined(__crayx1) \
    /**/
#  define BOOST_OLD_IOSTREAMS
# endif
#endif // #ifndef BOOST_OLD_IOSTREAMS

#ifndef _STLP_NO_IOSTREAMS
# ifndef BOOST_OLD_IOSTREAMS
#  include <ostream>
# else
#  include <ostream.h>
# endif
#endif // _STLP_NO_IOSTREAMS

#include <boost/range/iterator_range_core.hpp>
#include <iterator>
#include <algorithm>
#include <cstddef>

namespace boost
{

#ifndef _STLP_NO_IOSTREAMS
# ifndef BOOST_OLD_IOSTREAMS

        //! iterator_range output operator
        /*!
            Output the range to an ostream. Elements are outputted
            in a sequence without separators.
        */
        template< typename IteratorT, typename Elem, typename Traits >
        inline std::basic_ostream<Elem,Traits>& operator<<(
                    std::basic_ostream<Elem, Traits>& Os,
                    const iterator_range<IteratorT>& r )
        {
            std::copy( r.begin(), r.end(),
                       std::ostream_iterator< BOOST_DEDUCED_TYPENAME
                                              iterator_value<IteratorT>::type,
                                              Elem, Traits>(Os) );
            return Os;
        }

# else

        //! iterator_range output operator
        /*!
            Output the range to an ostream. Elements are outputted
            in a sequence without separators.
        */
        template< typename IteratorT >
        inline std::ostream& operator<<(
                    std::ostream& Os,
                    const iterator_range<IteratorT>& r )
        {
            std::copy( r.begin(), r.end(), std::ostream_iterator<char>(Os));
            return Os;
        }

# endif
#endif // _STLP_NO_IOSTREAMS

} // namespace boost

#undef BOOST_OLD_IOSTREAMS

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
    #pragma warning(pop)
#endif

#endif // include guard


code:
// Boost.Range library
//
//  Copyright Neil Groves 2009. Use, modification and
//  distribution is subject to 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)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_JOIN_HPP_INCLUDED
#define BOOST_RANGE_JOIN_HPP_INCLUDED

#include <boost/config.hpp>
#include <boost/range/detail/join_iterator.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/iterator_range.hpp>

namespace boost
{
    namespace range_detail
    {

template<class SinglePassRange1, class SinglePassRange2>
class joined_type
{
public:
    typedef iterator_range<
        range_detail::join_iterator<
            BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange1>::type,
            BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange2>::type,
            BOOST_DEDUCED_TYPENAME range_value<SinglePassRange1>::type
        >
    > type;
};

    } // namespace range_detail

namespace range
{

template<class SinglePassRange1, class SinglePassRange2>
class joined_range
    : public range_detail::joined_type<SinglePassRange1, SinglePassRange2>::type
{
    typedef range_detail::join_iterator<
        BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange1>::type,
        BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange2>::type,
        BOOST_DEDUCED_TYPENAME range_value<SinglePassRange1>::type
        > iterator_t;

    typedef BOOST_DEDUCED_TYPENAME range_detail::joined_type<
                    SinglePassRange1, SinglePassRange2>::type base_t;
public:
    joined_range(SinglePassRange1& rng1, SinglePassRange2& rng2)
        : base_t(
            iterator_t(rng1, rng2, range_detail::join_iterator_begin_tag()),
            iterator_t(rng1, rng2, range_detail::join_iterator_end_tag())
        )
    {
    }
};

template<class SinglePassRange1, class SinglePassRange2>
joined_range<const SinglePassRange1, const SinglePassRange2>
join(const SinglePassRange1& r1, const SinglePassRange2& r2)
{
    BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange1> ));
    BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange2> ));

    return joined_range<const SinglePassRange1, const SinglePassRange2>(r1, r2);
}

template<class SinglePassRange1, class SinglePassRange2>
joined_range<SinglePassRange1, SinglePassRange2>
join(SinglePassRange1& r1, SinglePassRange2& r2)
{
    BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange1> ));
    BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept<SinglePassRange2> ));

    return joined_range<SinglePassRange1, SinglePassRange2>(r1, r2);
}

} // namespace range

using ::boost::range::joined_range;
using ::boost::range::join;

} // namespace boost

#endif // include guard


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_METAFUNCTIONS_HPP
#define BOOST_RANGE_METAFUNCTIONS_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/iterator.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/range/result_iterator.hpp>
#include <boost/range/reverse_iterator.hpp>
#include <boost/range/const_reverse_iterator.hpp>
#include <boost/range/reverse_result_iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/size_type.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/category.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/pointer.hpp>

#endif


code:
#ifndef BOOST_RANGE_MFC_HPP
#define BOOST_RANGE_MFC_HPP

// Boost.Range MFC Extension
//
// Copyright Shunsuke Sogame 2005-2006.
// 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)

// config
//

#include <afx.h> // _MFC_VER

#if !defined(BOOST_RANGE_MFC_NO_CPAIR)
    #if (_MFC_VER < 0x0700) // dubious
        #define BOOST_RANGE_MFC_NO_CPAIR
    #endif
#endif

#if !defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)
    #if (_MFC_VER < 0x0700) // dubious
        #define BOOST_RANGE_MFC_HAS_LEGACY_STRING
    #endif
#endif

// A const collection of old MFC doesn't return const reference.
//
#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
    #if (_MFC_VER < 0x0700) // dubious
        #define BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF
    #endif
#endif

// forward declarations
//

template< class Type, class ArgType >
class CArray;

template< class Type, class ArgType >
class CList;

template< class Key, class ArgKey, class Mapped, class ArgMapped >
class CMap;

template< class BaseClass, class PtrType >
class CTypedPtrArray;

template< class BaseClass, class PtrType >
class CTypedPtrList;

template< class BaseClass, class KeyPtrType, class MappedPtrType >
class CTypedPtrMap;

// extended customizations
//

#include <cstddef> // ptrdiff_t
#include <utility> // pair
#include <boost/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/range/atl.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/detail/microsoft.hpp>
#include <boost/range/end.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/utility/addressof.hpp>
#include <afx.h> // legacy CString
#include <afxcoll.h> // CXXXArray, CXXXList, CMapXXXToXXX
#include <tchar.h>

namespace boost { namespace range_detail_microsoft {

    // mfc_ptr_array_iterator
    //
    // 'void **' is not convertible to 'void const **',
    // so we define...
    //

    template< class ArrayT, class PtrType >
    struct mfc_ptr_array_iterator;

    template< class ArrayT, class PtrType >
    struct mfc_ptr_array_iterator_super
    {
        typedef iterator_adaptor<
            mfc_ptr_array_iterator<ArrayT, PtrType>,
            std::ptrdiff_t, // Base!
            PtrType,        // Value
            random_access_traversal_tag,
            use_default,
            std::ptrdiff_t  // Difference
        > type;
    };

    template< class ArrayT, class PtrType >
    struct mfc_ptr_array_iterator :
        mfc_ptr_array_iterator_super<ArrayT, PtrType>::type
    {
    private:
        typedef mfc_ptr_array_iterator self_t;
        typedef typename mfc_ptr_array_iterator_super<ArrayT, PtrType>::type super_t;
        typedef typename super_t::reference ref_t;

    public:
        explicit mfc_ptr_array_iterator()
        { }

        explicit mfc_ptr_array_iterator(ArrayT& arr, INT_PTR index) :
            super_t(index), m_parr(boost::addressof(arr))
        { }

    template< class, class > friend struct mfc_ptr_array_iterator;
        template< class ArrayT_, class PtrType_ >
        mfc_ptr_array_iterator(mfc_ptr_array_iterator<ArrayT_, PtrType_> const& other) :
            super_t(other.base()), m_parr(other.m_parr)
        { }

    private:
        ArrayT *m_parr;

    friend class iterator_core_access;
        ref_t dereference() const
        {
            BOOST_ASSERT(0 <= this->base() && this->base() < m_parr->GetSize() && "out of range");
            return *( m_parr->GetData() + this->base() );
        }

        bool equal(self_t const& other) const
        {
            BOOST_ASSERT(m_parr == other.m_parr && "iterators incompatible");
            return this->base() == other.base();
        }
    };

    struct mfc_ptr_array_functions
    {
        template< class Iterator, class X >
        Iterator begin(X& x)
        {
            return Iterator(x, 0);
        }

        template< class Iterator, class X >
        Iterator end(X& x)
        {
            return Iterator(x, x.GetSize());
        }
    };

    // arrays
    //

    template< >
    struct customization< ::CByteArray > :
        array_functions
    {
        template< class X >
        struct meta
        {
            typedef BYTE val_t;

            typedef val_t *mutable_iterator;
            typedef val_t const *const_iterator;
        };
    };

    template< >
    struct customization< ::CDWordArray > :
        array_functions
    {
        template< class X >
        struct meta
        {
            typedef DWORD val_t;

            typedef val_t *mutable_iterator;
            typedef val_t const *const_iterator;
        };
    };

    template< >
    struct customization< ::CObArray > :
        mfc_ptr_array_functions
    {
        template< class X >
        struct meta
        {
            typedef mfc_ptr_array_iterator<X, CObject *> mutable_iterator;
            typedef mfc_ptr_array_iterator<X const, CObject const *> const_iterator;
        };
    };

    template< >
    struct customization< ::CPtrArray > :
        mfc_ptr_array_functions
    {
        template< class X >
        struct meta
        {
            typedef mfc_ptr_array_iterator<X, void *> mutable_iterator;
            typedef mfc_ptr_array_iterator<X const, void const *> const_iterator;
        };
    };

    template< >
    struct customization< ::CStringArray > :
        array_functions
    {
        template< class X >
        struct meta
        {
            typedef ::CString val_t;

            typedef val_t *mutable_iterator;
            typedef val_t const *const_iterator;
        };
    };

    template< >
    struct customization< ::CUIntArray > :
        array_functions
    {
        template< class X >
        struct meta
        {
            typedef UINT val_t;

            typedef val_t *mutable_iterator;
            typedef val_t const *const_iterator;
        };
    };

    template< >
    struct customization< ::CWordArray > :
        array_functions
    {
        template< class X >
        struct meta
        {
            typedef WORD val_t;

            typedef val_t *mutable_iterator;
            typedef val_t const *const_iterator;
        };
    };

    // lists
    //

    template< >
    struct customization< ::CObList > :
        list_functions
    {
        template< class X >
        struct meta
        {
            typedef list_iterator<X, ::CObject *> mutable_iterator;
    #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
            typedef list_iterator<X const, ::CObject const *> const_iterator;
    #else
            typedef list_iterator<X const, ::CObject const * const, ::CObject const * const> const_iterator;
    #endif
        };
    };

    template< >
    struct customization< ::CPtrList > :
        list_functions
    {
        template< class X >
        struct meta
        {
            typedef list_iterator<X, void *> mutable_iterator;
    #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
            typedef list_iterator<X const, void const *> const_iterator;
    #else
            typedef list_iterator<X const, void const * const, void const * const> const_iterator;
    #endif
        };
    };

    template< >
    struct customization< ::CStringList > :
        list_functions
    {
        template< class X >
        struct meta
        {
            typedef ::CString val_t;

            typedef list_iterator<X, val_t> mutable_iterator;
    #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
            typedef list_iterator<X const, val_t const> const_iterator;
    #else
            typedef list_iterator<X const, val_t const, val_t const> const_iterator;
    #endif
        };
    };

    // mfc_map_iterator
    //

    template< class MapT, class KeyT, class MappedT >
    struct mfc_map_iterator;

    template< class MapT, class KeyT, class MappedT >
    struct mfc_map_iterator_super
    {
        typedef iterator_facade<
            mfc_map_iterator<MapT, KeyT, MappedT>,
            std::pair<KeyT, MappedT>,
            forward_traversal_tag,
            std::pair<KeyT, MappedT> const
        > type;
    };

    template< class MapT, class KeyT, class MappedT >
    struct mfc_map_iterator :
        mfc_map_iterator_super<MapT, KeyT, MappedT>::type
    {
    private:
        typedef mfc_map_iterator self_t;
        typedef typename mfc_map_iterator_super<MapT, KeyT, MappedT>::type super_t;
        typedef typename super_t::reference ref_t;

    public:
        explicit mfc_map_iterator()
        { }

        explicit mfc_map_iterator(MapT const& map, POSITION pos) :
            m_pmap(boost::addressof(map)), m_posNext(pos)
        {
            increment();
        }

        explicit mfc_map_iterator(MapT const& map) :
            m_pmap(&map), m_pos(0) // end iterator
        { }

    template< class, class, class > friend struct mfc_map_iterator;
        template< class MapT_, class KeyT_, class MappedT_>
        mfc_map_iterator(mfc_map_iterator<MapT_, KeyT_, MappedT_> const& other) :
            m_pmap(other.m_pmap),
            m_pos(other.m_pos), m_posNext(other.m_posNext),
            m_key(other.m_key), m_mapped(other.m_mapped)
        { }

    private:
        MapT const *m_pmap;
        POSITION m_pos, m_posNext;
        KeyT m_key; MappedT m_mapped;

    friend class iterator_core_access;
        ref_t dereference() const
        {
            BOOST_ASSERT(m_pos != 0 && "out of range");
            return std::make_pair(m_key, m_mapped);
        }

        void increment()
        {
            BOOST_ASSERT(m_pos != 0 && "out of range");

            if (m_posNext == 0) {
                m_pos = 0;
                return;
            }

            m_pos = m_posNext;
            m_pmap->GetNextAssoc(m_posNext, m_key, m_mapped);
        }

        bool equal(self_t const& other) const
        {
            BOOST_ASSERT(m_pmap == other.m_pmap && "iterators incompatible");
            return m_pos == other.m_pos;
        }
    };

    struct mfc_map_functions
    {
        template< class Iterator, class X >
        Iterator begin(X& x)
        {
            return Iterator(x, x.GetStartPosition());
        }

        template< class Iterator, class X >
        Iterator end(X& x)
        {
            return Iterator(x);
        }
    };

#if !defined(BOOST_RANGE_MFC_NO_CPAIR)

    // mfc_cpair_map_iterator
    //
    // used by ::CMap and ::CMapStringToString
    //

    template< class MapT, class PairT >
    struct mfc_cpair_map_iterator;

    template< class MapT, class PairT >
    struct mfc_pget_map_iterator_super
    {
        typedef iterator_facade<
            mfc_cpair_map_iterator<MapT, PairT>,
            PairT,
            forward_traversal_tag
        > type;
    };

    template< class MapT, class PairT >
    struct mfc_cpair_map_iterator :
        mfc_pget_map_iterator_super<MapT, PairT>::type
    {
    private:
        typedef mfc_cpair_map_iterator self_t;
        typedef typename mfc_pget_map_iterator_super<MapT, PairT>::type super_t;
        typedef typename super_t::reference ref_t;

    public:
        explicit mfc_cpair_map_iterator()
        { }

        explicit mfc_cpair_map_iterator(MapT& map, PairT *pp) :
            m_pmap(boost::addressof(map)), m_pp(pp)
        { }

    template< class, class > friend struct mfc_cpair_map_iterator;
        template< class MapT_, class PairT_>
        mfc_cpair_map_iterator(mfc_cpair_map_iterator<MapT_, PairT_> const& other) :
            m_pmap(other.m_pmap), m_pp(other.m_pp)
        { }

    private:
        MapT  *m_pmap;
        PairT *m_pp;

    friend class iterator_core_access;
        ref_t dereference() const
        {
            BOOST_ASSERT(m_pp != 0 && "out of range");
            return *m_pp;
        }

        void increment()
        {
            BOOST_ASSERT(m_pp != 0 && "out of range");
            m_pp = m_pmap->PGetNextAssoc(m_pp);
        }

        bool equal(self_t const& other) const
        {
            BOOST_ASSERT(m_pmap == other.m_pmap && "iterators incompatible");
            return m_pp == other.m_pp;
        }
    };

    struct mfc_cpair_map_functions
    {
        template< class Iterator, class X >
        Iterator begin(X& x)
        {
            // Workaround:
            // Assertion fails if empty.
            // MFC document is wrong.
    #if !defined(NDEBUG)
            if (x.GetCount() == 0)
                return Iterator(x, 0);
    #endif

            return Iterator(x, x.PGetFirstAssoc());
        }

        template< class Iterator, class X >
        Iterator end(X& x)
        {
            return Iterator(x, 0);
        }
    };

#endif // !defined(BOOST_RANGE_MFC_NO_CPAIR)

    // maps
    //

    template< >
    struct customization< ::CMapPtrToWord > :
        mfc_map_functions
    {
        template< class X >
        struct meta
        {
            typedef void *key_t;
            typedef WORD mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
        };
    };

    template< >
    struct customization< ::CMapPtrToPtr > :
        mfc_map_functions
    {
        template< class X >
        struct meta
        {
            typedef void *key_t;
            typedef void *mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
        };
    };

    template< >
    struct customization< ::CMapStringToOb > :
        mfc_map_functions
    {
        template< class X >
        struct meta
        {
            typedef ::CString key_t;
            typedef ::CObject *mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
        };
    };

    template< >
    struct customization< ::CMapStringToPtr > :
        mfc_map_functions
    {
        template< class X >
        struct meta
        {
            typedef ::CString key_t;
            typedef void *mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
        };
    };

    template< >
    struct customization< ::CMapStringToString > :
    #if !defined(BOOST_RANGE_MFC_NO_CPAIR)
        mfc_cpair_map_functions
    #else
        mfc_map_functions
    #endif
    {
        template< class X >
        struct meta
        {
    #if !defined(BOOST_RANGE_MFC_NO_CPAIR)
            typedef typename X::CPair pair_t;

            typedef mfc_cpair_map_iterator<X, pair_t> mutable_iterator;
            typedef mfc_cpair_map_iterator<X const, pair_t const> const_iterator;
    #else
            typedef ::CString key_t;
            typedef ::CString mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
    #endif
        };
    };

    template< >
    struct customization< ::CMapWordToOb > :
        mfc_map_functions
    {
        template< class X >
        struct meta
        {
            typedef WORD key_t;
            typedef ::CObject *mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
        };
    };

    template< >
    struct customization< ::CMapWordToPtr > :
        mfc_map_functions
    {
        template< class X >
        struct meta
        {
            typedef WORD key_t;
            typedef void *mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
        };
    };

    // templates
    //

    template< class Type, class ArgType >
    struct customization< ::CArray<Type, ArgType> > :
        array_functions
    {
        template< class X >
        struct meta
        {
            typedef Type val_t;

            typedef val_t *mutable_iterator;
            typedef val_t const *const_iterator;
        };
    };

    template< class Type, class ArgType >
    struct customization< ::CList<Type, ArgType> > :
        list_functions
    {
        template< class X >
        struct meta
        {
            typedef Type val_t;

            typedef list_iterator<X, val_t> mutable_iterator;
    #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
            typedef list_iterator<X const, val_t const> const_iterator;
    #else
            typedef list_iterator<X const, val_t const, val_t const> const_iterator;
    #endif
        };
    };

    template< class Key, class ArgKey, class Mapped, class ArgMapped >
    struct customization< ::CMap<Key, ArgKey, Mapped, ArgMapped> > :
    #if !defined(BOOST_RANGE_MFC_NO_CPAIR)
        mfc_cpair_map_functions
    #else
        mfc_map_functions
    #endif
    {
        template< class X >
        struct meta
        {
    #if !defined(BOOST_RANGE_MFC_NO_CPAIR)
            typedef typename X::CPair pair_t;

            typedef mfc_cpair_map_iterator<X, pair_t> mutable_iterator;
            typedef mfc_cpair_map_iterator<X const, pair_t const> const_iterator;
    #else
            typedef Key key_t;
            typedef Mapped mapped_t;

            typedef mfc_map_iterator<X, key_t, mapped_t> mutable_iterator;
            typedef mutable_iterator const_iterator;
    #endif
        };
    };

    template< class BaseClass, class PtrType >
    struct customization< ::CTypedPtrArray<BaseClass, PtrType> >
    {
        template< class X >
        struct fun
        {
            typedef typename remove_pointer<PtrType>::type val_t;

            typedef typename mpl::if_< is_const<X>,
                val_t const,
                val_t
            >::type val_t_;

            typedef val_t_ * const result_type;

            template< class PtrType_ >
            result_type operator()(PtrType_ p) const
            {
                return static_cast<result_type>(p);
            }
        };

        template< class X >
        struct meta
        {
            typedef typename compatible_mutable_iterator<BaseClass>::type miter_t;
            typedef typename range_const_iterator<BaseClass>::type citer_t;

            typedef transform_iterator<fun<X>, miter_t> mutable_iterator;
            typedef transform_iterator<fun<X const>, citer_t> const_iterator;
        };

        template< class Iterator, class X >
        Iterator begin(X& x)
        {
            return Iterator(boost::begin<BaseClass>(x), fun<X>());
        }

        template< class Iterator, class X >
        Iterator end(X& x)
        {
            return Iterator(boost::end<BaseClass>(x), fun<X>());
        }
    };

    template< class BaseClass, class PtrType >
    struct customization< ::CTypedPtrList<BaseClass, PtrType> > :
        list_functions
    {
        template< class X >
        struct meta
        {
            typedef typename remove_pointer<PtrType>::type val_t;

            // not l-value
            typedef list_iterator<X, val_t * const, val_t * const> mutable_iterator;
            typedef list_iterator<X const, val_t const * const, val_t const * const> const_iterator;
        };
    };

    template< class BaseClass, class KeyPtrType, class MappedPtrType >
    struct customization< ::CTypedPtrMap<BaseClass, KeyPtrType, MappedPtrType> > :
        mfc_map_functions
    {
        template< class X >
        struct meta
        {
            typedef mfc_map_iterator<X, KeyPtrType, MappedPtrType> mutable_iterator;
            typedef mutable_iterator const_iterator;
        };
    };

    // strings
    //

#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)

    template< >
    struct customization< ::CString >
    {
        template< class X >
        struct meta
        {
            // LPTSTR/LPCTSTR is not always defined in <tchar.h>.
            typedef TCHAR *mutable_iterator;
            typedef TCHAR const *const_iterator;
        };

        template< class Iterator, class X >
        typename mutable_<Iterator, X>::type begin(X& x)
        {
            return x.GetBuffer(0);
        }

        template< class Iterator, class X >
        Iterator begin(X const& x)
        {
            return x;
        }

        template< class Iterator, class X >
        Iterator end(X& x)
        {
            return begin<Iterator>(x) + x.GetLength();
        }
    };

#endif // defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)

} } // namespace boost::range_detail_microsoft

// range customizations
//

// arrays
//
BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CByteArray
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CDWordArray
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CStringArray
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CUIntArray
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CWordArray
)

// lists
//
BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CObList
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CPtrList
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CStringList
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CObArray
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CPtrArray
)

// maps
//
BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMapPtrToWord
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMapPtrToPtr
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMapStringToOb
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMapStringToPtr
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMapStringToString
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMapWordToOb
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMapWordToPtr
)

// templates
//
BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CArray, 2
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CList, 2
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CMap, 4
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CTypedPtrArray, 2
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CTypedPtrList, 2
)

BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE(
    boost::range_detail_microsoft::using_type_as_tag,
    BOOST_PP_NIL, CTypedPtrMap, 3
)

// strings
//
#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)

    BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(
        boost::range_detail_microsoft::using_type_as_tag,
        BOOST_PP_NIL, CString
    )

#endif

#endif


code:
// Boost.Range library
//
//  Copyright Adam D. Walling 2012. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_ADAPTOR_MFC_MAP_HPP
#define BOOST_RANGE_ADAPTOR_MFC_MAP_HPP

#if !defined(BOOST_RANGE_MFC_NO_CPAIR)

#include <boost/range/mfc.hpp>
#include <boost/range/adaptor/map.hpp>

namespace boost
{
    namespace range_detail
    {
        // CMap and CMapStringToString range iterators return CPair,
        // which has a key and value member. Other MFC range iterators
        // already return adapted std::pair objects. This allows usage
        // of the map_keys and map_values range adaptors with CMap
        // and CMapStringToString

        // CPair has a VALUE value member, and a KEY key member; we will
        // use VALUE& as the result_type consistent with CMap::operator[]

        // specialization for CMap
        template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
        struct select_first< CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> >
        {
            typedef BOOST_DEDUCED_TYPENAME CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> map_type;
            typedef BOOST_DEDUCED_TYPENAME range_reference<const map_type>::type argument_type;
            typedef BOOST_DEDUCED_TYPENAME const KEY& result_type;

            result_type operator()( argument_type r ) const
            {
                return r.key;
            }
        };

        template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
        struct select_second_mutable< CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> >
        {
            typedef BOOST_DEDUCED_TYPENAME CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> map_type;
            typedef BOOST_DEDUCED_TYPENAME range_reference<map_type>::type argument_type;
            typedef BOOST_DEDUCED_TYPENAME VALUE& result_type;

            result_type operator()( argument_type r ) const
            {
                return r.value;
            }
        };

        template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
        struct select_second_const< CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> >
        {
            typedef BOOST_DEDUCED_TYPENAME CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> map_type;
            typedef BOOST_DEDUCED_TYPENAME range_reference<const map_type>::type argument_type;
            typedef BOOST_DEDUCED_TYPENAME const VALUE& result_type;

            result_type operator()( argument_type r ) const
            {
                return r.value;
            }
        };

        // specialization for CMapStringToString
        template<>
        struct select_first< CMapStringToString >
        {
            typedef range_reference<const CMapStringToString>::type argument_type;
            typedef const CString& result_type;

            result_type operator()( argument_type r ) const
            {
                return r.key;
            }
        };

        template<>
        struct select_second_mutable< CMapStringToString >
        {
            typedef range_reference<CMapStringToString>::type argument_type;
            typedef CString& result_type;

            result_type operator()( argument_type r ) const
            {
                return r.value;
            }
        };

        template<>
        struct select_second_const< CMapStringToString >
        {
            typedef range_reference<const CMapStringToString>::type argument_type;
            typedef const CString& result_type;

            result_type operator()( argument_type r ) const
            {
                return r.value;
            }
        };
    } // 'range_detail'
} // 'boost'

#endif // !defined(BOOST_RANGE_MFC_NO_CPAIR)

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_MUTABLE_ITERATOR_HPP
#define BOOST_RANGE_MUTABLE_ITERATOR_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>

#include <boost/range/range_fwd.hpp>
#include <boost/range/detail/extract_optional_type.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <cstddef>
#include <utility>

namespace boost
{

    //////////////////////////////////////////////////////////////////////////
    // default
    //////////////////////////////////////////////////////////////////////////

    namespace range_detail
    {

BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( iterator )

template< typename C >
struct range_mutable_iterator
        : range_detail::extract_iterator<
            BOOST_DEDUCED_TYPENAME remove_reference<C>::type>
{};

//////////////////////////////////////////////////////////////////////////
// pair
//////////////////////////////////////////////////////////////////////////

template< typename Iterator >
struct range_mutable_iterator< std::pair<Iterator,Iterator> >
{
    typedef Iterator type;
};

//////////////////////////////////////////////////////////////////////////
// array
//////////////////////////////////////////////////////////////////////////

template< typename T, std::size_t sz >
struct range_mutable_iterator< T[sz] >
{
    typedef T* type;
};

    } // namespace range_detail

template<typename C, typename Enabler=void>
struct range_mutable_iterator
        : range_detail::range_mutable_iterator<
            BOOST_DEDUCED_TYPENAME remove_reference<C>::type
        >
{
};

} // namespace boost

#include <boost/range/detail/msvc_has_iterator_workaround.hpp>

#endif


code:
// Copyright 2009-2014 Neil Groves.
// 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)
//
// Copyright 2006 Thorsten Ottosen.
// 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)
//
// Copyright 2004 Eric Niebler.
// 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)
//
//   Contains range-based versions of the numeric std algorithms
//
#if defined(_MSC_VER)
    #pragma once
#endif

#ifndef BOOST_RANGE_NUMERIC_HPP
#define BOOST_RANGE_NUMERIC_HPP

#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/category.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/distance.hpp>
#include <boost/range/size.hpp>
#include <numeric>

namespace boost
{
    template<class SinglePassRange, class Value>
    inline Value accumulate(const SinglePassRange& rng, Value init)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
            SinglePassRangeConcept<const SinglePassRange>));

        return std::accumulate(boost::begin(rng), boost::end(rng), init);
    }

    template<class SinglePassRange, class Value, class BinaryOperation>
    inline Value accumulate(const SinglePassRange& rng, Value init,
                            BinaryOperation op)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
                SinglePassRangeConcept<const SinglePassRange> ));

        return std::accumulate(boost::begin(rng), boost::end(rng), init, op);
    }

    namespace range_detail
    {
        template<class SinglePassRange1, class SinglePassRange2>
        inline bool inner_product_precondition(
            const SinglePassRange1&,
            const SinglePassRange2&,
            std::input_iterator_tag,
            std::input_iterator_tag)
        {
            return true;
        }

        template<class SinglePassRange1, class SinglePassRange2>
        inline bool inner_product_precondition(
            const SinglePassRange1& rng1,
            const SinglePassRange2& rng2,
            std::forward_iterator_tag,
            std::forward_iterator_tag)
        {
            return boost::size(rng2) >= boost::size(rng1);
        }

    } // namespace range_detail

    template<
        class SinglePassRange1,
        class SinglePassRange2,
        class Value
    >
    inline Value inner_product(
        const SinglePassRange1& rng1,
        const SinglePassRange2& rng2,
        Value                   init)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
            SinglePassRangeConcept<const SinglePassRange1>));

        BOOST_RANGE_CONCEPT_ASSERT((
            SinglePassRangeConcept<const SinglePassRange2>));

        BOOST_ASSERT(
            range_detail::inner_product_precondition(
                    rng1, rng2,
                    typename range_category<const SinglePassRange1>::type(),
                    typename range_category<const SinglePassRange2>::type()));

        return std::inner_product(
            boost::begin(rng1), boost::end(rng1),
            boost::begin(rng2), init);
    }

    template<
        class SinglePassRange1,
        class SinglePassRange2,
        class Value,
        class BinaryOperation1,
        class BinaryOperation2
    >
    inline Value inner_product(
        const SinglePassRange1& rng1,
        const SinglePassRange2& rng2,
        Value                   init,
        BinaryOperation1        op1,
        BinaryOperation2        op2)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
                SinglePassRangeConcept<const SinglePassRange1>));

        BOOST_RANGE_CONCEPT_ASSERT((
                SinglePassRangeConcept<const SinglePassRange2>));

        BOOST_ASSERT(
            range_detail::inner_product_precondition(
                rng1, rng2,
                typename range_category<const SinglePassRange1>::type(),
                typename range_category<const SinglePassRange2>::type()));

        return std::inner_product(
            boost::begin(rng1), boost::end(rng1),
            boost::begin(rng2), init, op1, op2);
    }

    template<class SinglePassRange, class OutputIterator>
    inline OutputIterator partial_sum(const SinglePassRange& rng,
                                      OutputIterator result)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
                SinglePassRangeConcept<const SinglePassRange>));

        return std::partial_sum(boost::begin(rng), boost::end(rng), result);
    }

    template<class SinglePassRange, class OutputIterator, class BinaryOperation>
    inline OutputIterator partial_sum(
        const SinglePassRange&  rng,
        OutputIterator          result,
        BinaryOperation         op)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
                SinglePassRangeConcept<const SinglePassRange>));

        return std::partial_sum(boost::begin(rng), boost::end(rng), result, op);
    }

    template<class SinglePassRange, class OutputIterator>
    inline OutputIterator adjacent_difference(
        const SinglePassRange&  rng,
        OutputIterator          result)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
                SinglePassRangeConcept<const SinglePassRange>));

        return std::adjacent_difference(boost::begin(rng), boost::end(rng),
                                        result);
    }

    template<class SinglePassRange, class OutputIterator, class BinaryOperation>
    inline OutputIterator adjacent_difference(
        const SinglePassRange&  rng,
        OutputIterator          result,
        BinaryOperation         op)
    {
        BOOST_RANGE_CONCEPT_ASSERT((
                SinglePassRangeConcept<const SinglePassRange>));

        return std::adjacent_difference(boost::begin(rng), boost::end(rng),
                                        result, op);
    }

} // namespace boost

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2006. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_POINTER_TYPE_HPP
#define BOOST_RANGE_POINTER_TYPE_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>
#include <boost/range/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>

namespace boost
{
    template< class T >
    struct range_pointer
            : iterator_pointer< BOOST_DEDUCED_TYPENAME range_iterator<T>::type >
    { };
}

#endif


code:
// Boost.Range library
//
//  Copyright Neil Groves 2003-2004.
//  Use, modification and distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_RANGE_FWD_HPP_INCLUDED
#define BOOST_RANGE_RANGE_FWD_HPP_INCLUDED

namespace boost
{

// Extension points
    template<typename C, typename Enabler>
    struct range_iterator;

    template<typename C, typename Enabler>
    struct range_mutable_iterator;

    template<typename C, typename Enabler>
    struct range_const_iterator;

// Core classes
    template<typename IteratorT>
    class iterator_range;

    template<typename ForwardRange>
    class sub_range;

// Meta-functions
    template<typename T>
    struct range_category;

    template<typename T>
    struct range_difference;

    template<typename T>
    struct range_pointer;

    template<typename T>
    struct range_reference;

    template<typename T>
    struct range_reverse_iterator;

    template<typename T>
    struct range_size;

    template<typename T>
    struct range_value;

    template<typename T>
    struct has_range_iterator;

    template<typename T>
    struct has_range_const_iterator;

} // namespace boost

#endif // include guard


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_RBEGIN_HPP
#define BOOST_RANGE_RBEGIN_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/end.hpp>
#include <boost/range/reverse_iterator.hpp>

namespace boost
{

#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING

template< class C >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type
rbegin( C& c )
{
    return BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type( boost::end( c ) );
}

#else

template< class C >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type
rbegin( C& c )
{
    typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type
        iter_type;
    return iter_type( boost::end( c ) );
}

template< class C >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<const C>::type
rbegin( const C& c )
{
    typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator<const C>::type
        iter_type;
    return iter_type( boost::end( c ) );
}

#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING

template< class T >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<const T>::type
const_rbegin( const T& r )
{
    return boost::rbegin( r );
}

} // namespace 'boost'

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_REFERENCE_TYPE_HPP
#define BOOST_RANGE_REFERENCE_TYPE_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>
#include <boost/range/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>

namespace boost
{
    template< class T >
    struct range_reference : iterator_reference< typename range_iterator<T>::type >
    { };
}

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_REND_HPP
#define BOOST_RANGE_REND_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/begin.hpp>
#include <boost/range/reverse_iterator.hpp>

namespace boost
{

#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING

template< class C >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type
rend( C& c )
{
    return BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type( boost::begin( c ) );
}

#else

template< class C >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type
rend( C& c )
{
    typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator<C>::type
               iter_type;
    return iter_type( boost::begin( c ) );
}

template< class C >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<const C>::type
rend( const C& c )
{
    typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator<const C>::type
        iter_type;
    return iter_type( boost::begin( c ) );
}

#endif

template< class T >
inline BOOST_DEDUCED_TYPENAME range_reverse_iterator<const T>::type
const_rend( const T& r )
{
    return boost::rend( r );
}

} // namespace 'boost'

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_RESULT_ITERATOR_HPP
#define BOOST_RANGE_RESULT_ITERATOR_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/iterator.hpp>

namespace boost
{
    //
    // This interface is deprecated, use range_iterator<T>
    //

    template< typename C >
    struct range_result_iterator : range_iterator<C>
    { };

} // namespace boost

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_REVERSE_ITERATOR_HPP
#define BOOST_RANGE_REVERSE_ITERATOR_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>
#include <boost/range/iterator.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/iterator/reverse_iterator.hpp>

namespace boost
{
    //////////////////////////////////////////////////////////////////////////
    // default
    //////////////////////////////////////////////////////////////////////////

    template< typename T >
    struct range_reverse_iterator
    {
        typedef reverse_iterator<
            BOOST_DEDUCED_TYPENAME range_iterator<
                BOOST_DEDUCED_TYPENAME remove_reference<T>::type>::type > type;
    };

} // namespace boost

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_REVERSE_RESULT_ITERATOR_HPP
#define BOOST_RANGE_REVERSE_RESULT_ITERATOR_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/reverse_iterator.hpp>

namespace boost
{
    //
    // This interface is deprecated, use range_reverse_iterator<T>
    //

    template< typename C >
    struct range_reverse_result_iterator : range_reverse_iterator<C>
    { };

} // namespace boost

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_SIZE_HPP
#define BOOST_RANGE_SIZE_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size_type.hpp>
#include <boost/range/detail/has_member_size.hpp>
#include <boost/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/utility.hpp>

namespace boost
{
    namespace range_detail
    {

        template<class SinglePassRange>
        inline typename ::boost::enable_if<
            has_member_size<SinglePassRange>,
            typename range_size<const SinglePassRange>::type
        >::type
        range_calculate_size(const SinglePassRange& rng)
        {
            return rng.size();
        }

        template<class SinglePassRange>
        inline typename disable_if<
            has_member_size<SinglePassRange>,
            typename range_size<const SinglePassRange>::type
        >::type
        range_calculate_size(const SinglePassRange& rng)
        {
            return std::distance(boost::begin(rng), boost::end(rng));
        }
    }

    template<class SinglePassRange>
    inline typename range_size<const SinglePassRange>::type
    size(const SinglePassRange& rng)
    {
// Very strange things happen on some compilers that have the range concept
// asserts disabled. This preprocessor condition is clearly redundant on a
// working compiler but is vital for at least some compilers such as clang 4.2
// but only on the Mac!
#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1
        BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<SinglePassRange>));
#endif

#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
    !BOOST_WORKAROUND(__GNUC__, < 3) \
    /**/
        using namespace range_detail;
#endif

        return range_calculate_size(rng);
    }

} // namespace 'boost'

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_SIZE_TYPE_HPP
#define BOOST_RANGE_SIZE_TYPE_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/has_range_iterator.hpp>

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <cstddef>
#include <utility>

namespace boost
{
    namespace detail
    {

        //////////////////////////////////////////////////////////////////////////
        // default
        //////////////////////////////////////////////////////////////////////////

        template<typename T>
        class has_size_type
        {
            typedef char no_type;
            struct yes_type { char dummy[2]; };

            template<typename C>
            static yes_type test(BOOST_DEDUCED_TYPENAME C::size_type x);

            template<typename C>
            static no_type test(...);

        public:
            static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
        };

        template<typename C, typename Enabler=void>
        struct range_size_
        {
            typedef BOOST_DEDUCED_TYPENAME make_unsigned<
                BOOST_DEDUCED_TYPENAME range_difference<C>::type
            >::type type;
        };

        template<typename C>
        struct range_size_<
            C,
            BOOST_DEDUCED_TYPENAME ::boost::enable_if<has_size_type<C>, void>::type
        >
        {
            typedef BOOST_DEDUCED_TYPENAME C::size_type type;
        };

        template<typename C, bool B = range_detail::has_type< range_iterator<C> >::value>
        struct range_size
        { };

        template<typename C>
        struct range_size<C, true>
          : range_size_<C>
        { };
    }

    template< class T >
    struct range_size :
        detail::range_size<T>
    { };

} // namespace boost

#endif


code:
// Boost.Range library
//
//  Copyright Neil Groves 2009.
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_SUB_RANGE_HPP
#define BOOST_RANGE_SUB_RANGE_HPP

#include <boost/detail/workaround.hpp>

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
    #pragma warning( push )
    #pragma warning( disable : 4996 )
#endif

#include <boost/range/config.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/size_type.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/algorithm/equal.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/remove_reference.hpp>

namespace boost
{
    namespace range_detail
    {

template<class ForwardRange, class TraversalTag>
class sub_range_base
        : public iterator_range<
            BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
        >
{
    typedef iterator_range<
        BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
    > base;

protected:
    typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_;

public:
    typedef BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type value_type;
    typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator;
    typedef BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type const_iterator;
    typedef BOOST_DEDUCED_TYPENAME range_difference<ForwardRange>::type difference_type;
    typedef BOOST_DEDUCED_TYPENAME range_size<ForwardRange>::type size_type;
    typedef BOOST_DEDUCED_TYPENAME range_reference<ForwardRange>::type reference;
    typedef BOOST_DEDUCED_TYPENAME range_reference<const ForwardRange>::type const_reference;

    sub_range_base()
    {
    }

    template<class Iterator>
    sub_range_base(Iterator first, Iterator last)
        : base(first, last)
    {
    }

    reference front()
    {
        return base::front();
    }

    const_reference front() const
    {
        return base::front();
    }
};

template<class ForwardRange>
class sub_range_base<ForwardRange, bidirectional_traversal_tag>
        : public sub_range_base<ForwardRange, forward_traversal_tag>
{
    typedef sub_range_base<ForwardRange, forward_traversal_tag> base;
public:
    sub_range_base()
    {
    }

    template<class Iterator>
    sub_range_base(Iterator first, Iterator last)
        : base(first, last)
    {
    }

    BOOST_DEDUCED_TYPENAME base::reference back()
    {
        return base::back();
    }

    BOOST_DEDUCED_TYPENAME base::const_reference back() const
    {
        return base::back();
    }
};

template<class ForwardRange>
class sub_range_base<ForwardRange, random_access_traversal_tag>
        : public sub_range_base<ForwardRange, bidirectional_traversal_tag>
{
    typedef sub_range_base<ForwardRange, bidirectional_traversal_tag> base;

public:
    sub_range_base()
    {
    }

    template<class Iterator>
    sub_range_base(Iterator first, Iterator last)
        : base(first, last)
    {
    }

    BOOST_DEDUCED_TYPENAME base::reference
    operator[](BOOST_DEDUCED_TYPENAME base::difference_type n)
    {
        return this->begin()[n];
    }

    BOOST_DEDUCED_TYPENAME base::const_reference
    operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) const
    {
        return this->begin()[n];
    }
};

    } // namespace range_detail

    template<class ForwardRange>
    class sub_range
        : public range_detail::sub_range_base<
                ForwardRange,
                BOOST_DEDUCED_TYPENAME iterator_traversal<
                    BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
                >::type
            >
    {
        typedef BOOST_DEDUCED_TYPENAME range_iterator<
            ForwardRange
        >::type iterator_t;

        typedef range_detail::sub_range_base<
            ForwardRange,
            BOOST_DEDUCED_TYPENAME iterator_traversal<
                BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
            >::type
        > base;

        typedef BOOST_DEDUCED_TYPENAME base::impl impl;

    protected:
        typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_;

    private:
        template<class Source>
        struct is_compatible_range
            : is_convertible<
                BOOST_DEDUCED_TYPENAME mpl::eval_if<
                    has_range_iterator<Source>,
                    range_iterator<Source>,
                    mpl::identity<void>
                >::type,
                BOOST_DEDUCED_TYPENAME base::iterator
            >
        {
        };

    public:
        sub_range()
        { }

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) )
        sub_range(const sub_range& r)
            : base(impl::adl_begin(const_cast<base&>(static_cast<const base&>(r))),
                   impl::adl_end(const_cast<base&>(static_cast<const base&>(r))))
        { }
#endif

        template< class ForwardRange2 >
        sub_range(
            ForwardRange2& r,
            BOOST_DEDUCED_TYPENAME ::boost::enable_if<
                is_compatible_range<ForwardRange2>
            >::type* = 0
        )
        : base(impl::adl_begin(r), impl::adl_end(r))
        {
        }

        template< class ForwardRange2 >
        sub_range(
            const ForwardRange2& r,
            BOOST_DEDUCED_TYPENAME ::boost::enable_if<
                is_compatible_range<const ForwardRange2>
            >::type* = 0
        )
        : base(impl::adl_begin(r), impl::adl_end(r))
        {
        }

        BOOST_DEDUCED_TYPENAME base::const_iterator begin() const
        {
            return base::begin();
        }

        BOOST_DEDUCED_TYPENAME base::iterator begin()
        {
            return base::begin();
        }

        BOOST_DEDUCED_TYPENAME base::const_iterator end() const
        {
            return base::end();
        }

        BOOST_DEDUCED_TYPENAME base::iterator end()
        {
            return base::end();
        }

        template< class Iter >
        sub_range( Iter first, Iter last ) :
            base( first, last )
        { }

        template<class ForwardRange2>
        BOOST_DEDUCED_TYPENAME ::boost::enable_if<
            is_compatible_range<ForwardRange2>,
            sub_range&
        >::type
        operator=(ForwardRange2& r)
        {
            iterator_range_::operator=( r );
            return *this;
        }

        template<class ForwardRange2>
        BOOST_DEDUCED_TYPENAME ::boost::enable_if<
            is_compatible_range<const ForwardRange2>,
            sub_range&
        >::type
        operator=( const ForwardRange2& r )
        {
            iterator_range_::operator=( r );
            return *this;
        }

        sub_range& operator=( const sub_range& r )
        {
            iterator_range_::operator=( static_cast<const iterator_range_&>(r) );
            return *this;
        }

        sub_range& advance_begin(
            BOOST_DEDUCED_TYPENAME base::difference_type n)
        {
            std::advance(this->m_Begin, n);
            return *this;
        }

        sub_range& advance_end(
            BOOST_DEDUCED_TYPENAME base::difference_type n)
        {
            std::advance(this->m_End, n);
            return *this;
        }
    };

} // namespace 'boost'

#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
    #pragma warning( pop )
#endif

#endif


code:
// Boost.Range library
//
//  Copyright Neil Groves 2014. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_TRAVERSAL_HPP
#define BOOST_RANGE_TRAVERSAL_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>
#include <boost/range/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>

namespace boost
{
    template<typename SinglePassRange>
    struct range_traversal
        : iterator_traversal<typename range_iterator<SinglePassRange>::type>
    {
    };
}

#endif


code:
// Boost.Range library
//
//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
//  distribution is subject to 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)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_VALUE_TYPE_HPP
#define BOOST_RANGE_VALUE_TYPE_HPP

#if defined(_MSC_VER)
# pragma once
#endif

#include <boost/range/config.hpp>
#include <boost/range/iterator.hpp>

#include <boost/iterator/iterator_traits.hpp>

namespace boost
{
    template< class T >
    struct range_value : iterator_value< typename range_iterator<T>::type >
    { };
}

#endif


code:
//  config.hpp  ---------------------------------------------------------------//

//  Copyright 2012 Vicente J. Botet Escriba

//  Distributed under the Boost Software License, Version 1.0.
//  See http://www.boost.org/LICENSE_1_0.txt

#ifndef BOOST_RATIO_CONFIG_HPP
#define BOOST_RATIO_CONFIG_HPP

#include <boost/config.hpp>
#include <boost/cstdint.hpp>

#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)
#  if ! defined BOOST_NO_CXX11_U16STRING
#    define BOOST_NO_CXX11_U16STRING
#  endif
#  if ! defined BOOST_NO_CXX11_U32STRING
#    define BOOST_NO_CXX11_U32STRING
#  endif
#endif

#if !defined BOOST_RATIO_VERSION
#define BOOST_RATIO_VERSION 1
#else
#if BOOST_RATIO_VERSION!=1  && BOOST_RATIO_VERSION!=2
#error "BOOST_RATIO_VERSION must be 1 or 2"
#endif
#endif

#if BOOST_RATIO_VERSION==1
#if ! defined BOOST_RATIO_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V2_0_0
#define BOOST_RATIO_PROVIDES_DEPRECATED_FEATURES_SINCE_V2_0_0
#endif
#endif

#if BOOST_RATIO_VERSION==2
#if ! defined BOOST_RATIO_PROVIDES_DEPRECATED_FEATURES_SINCE_V2_0_0
#define BOOST_RATIO_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V2_0_0
#endif
#endif

#ifdef INTMAX_C
#define BOOST_RATIO_INTMAX_C(a) INTMAX_C(a)
#else
#define BOOST_RATIO_INTMAX_C(a) a##LL
#endif

#ifdef UINTMAX_C
#define BOOST_RATIO_UINTMAX_C(a) UINTMAX_C(a)
#else
#define BOOST_RATIO_UINTMAX_C(a) a##ULL
#endif

#define BOOST_RATIO_INTMAX_T_MAX (0x7FFFFFFFFFFFFFFELL)

#ifndef BOOST_NO_CXX11_STATIC_ASSERT
#define BOOST_RATIO_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG)
#elif defined(BOOST_RATIO_USES_STATIC_ASSERT)
#include <boost/static_assert.hpp>
#define BOOST_RATIO_STATIC_ASSERT(CND, MSG, TYPES) BOOST_STATIC_ASSERT(CND)
#elif defined(BOOST_RATIO_USES_MPL_ASSERT)
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#define BOOST_RATIO_STATIC_ASSERT(CND, MSG, TYPES)                                 \
    BOOST_MPL_ASSERT_MSG(boost::mpl::bool_< (CND) >::type::value, MSG, TYPES)
#else
//~ #elif defined(BOOST_RATIO_USES_ARRAY_ASSERT)
#define BOOST_RATIO_CONCAT(A,B) A##B
#define BOOST_RATIO_NAME(A,B) BOOST_RATIO_CONCAT(A,B)
#define BOOST_RATIO_STATIC_ASSERT(CND, MSG, TYPES) static char BOOST_RATIO_NAME(__boost_ratio_test_,__LINE__)[(CND)?1:-1]
//~ #define BOOST_RATIO_STATIC_ASSERT(CND, MSG, TYPES)
#endif

#if !defined(BOOST_NO_CXX11_STATIC_ASSERT) || !defined(BOOST_RATIO_USES_MPL_ASSERT)
#define BOOST_RATIO_OVERFLOW_IN_ADD "overflow in ratio add"
#define BOOST_RATIO_OVERFLOW_IN_SUB "overflow in ratio sub"
#define BOOST_RATIO_OVERFLOW_IN_MUL "overflow in ratio mul"
#define BOOST_RATIO_OVERFLOW_IN_DIV "overflow in ratio div"
#define BOOST_RATIO_NUMERATOR_IS_OUT_OF_RANGE "ratio numerator is out of range"
#define BOOST_RATIO_DIVIDE_BY_0 "ratio divide by 0"
#define BOOST_RATIO_DENOMINATOR_IS_OUT_OF_RANGE "ratio denominator is out of range"
#endif

//#define BOOST_RATIO_EXTENSIONS

#endif  // header


code:
////////////////////////////////////////////////////////////////////
//
// Copyright Vicente J. Botet Escriba 2010
//
// 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)
//
// See http://www.boost.org/libs/mpl for documentation.
//
////////////////////////////////////////////////////////////////////
#ifndef BOOST_MPL_ABS_HPP_INCLUDED
#define BOOST_MPL_ABS_HPP_INCLUDED

#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/aux_/na_spec.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/mpl/aux_/config/integral.hpp>
#include <boost/mpl/aux_/config/static_constant.hpp>

#if    !defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC_2) \
    && !defined(BOOST_MPL_PREPROCESSING_MODE) \
    && !defined(__CUDACC__) \
    && ( defined(BOOST_MSVC) \
        || BOOST_WORKAROUND(__EDG_VERSION__, <= 238) \
        )

#   define BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC_2

#endif

namespace boost { namespace mpl {

template< typename Tag > struct abs_impl;

template< typename T > struct abs_tag
{
    typedef typename T::tag type;
};

template<
      typename BOOST_MPL_AUX_NA_PARAM(N)
    >
struct abs
    : abs_impl<
          typename abs_tag<N>::type
        >::template apply<N>::type
{
    BOOST_MPL_AUX_LAMBDA_SUPPORT(1, abs, (N))
};

BOOST_MPL_AUX_NA_SPEC(1, abs)

template<
      typename T
    , T n1
    >
struct abs_c
    : abs<integral_c<T,n1> >
{
};

#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC_2)
namespace aux {
template< typename T, T n > struct abs_wknd
{
    BOOST_STATIC_CONSTANT(T, value = (n < 0 ? -n : n));
    typedef integral_c<T,value> type;
};
}
#endif

template<>
struct abs_impl<integral_c_tag>
{
#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC_2)
    template< typename N > struct apply
        : aux::abs_wknd< typename N::value_type, N::value >
#else
    template< typename N > struct apply
        : integral_c< typename N::value_type, ((N::value < 0) ? (-N::value) : N::value ) >
#endif
    {
    };
};

}}

#endif // BOOST_MPL_ABS_HPP_INCLUDED